Вам не нужно второе правило перезаписи.
Ваш CSS существует здесь: /css/normalize.css
Ваша страница просматривает здесь: / swift-details /2/abblinbb/css/normalize.css
Все, что вам нужно, это «передние косые черты» перед вашими дорожками CSS / JS.
Используя споры ключевого слова со значениями по умолчанию (как предложено kquinn) хорошая идея, но потребует, чтобы Вы включали круглую скобку:
@redirect_output()
def foo():
...
, Если Вы хотели бы версию, которая работает без круглой скобки над декоратором, которого необходимо будет считать обоими сценариями в коде декоратора.
при использовании Python 3.0, Вы могли бы использовать ключевое слово только аргументы в пользу этого:
def redirect_output(fn=None,*,destination=None):
destination = sys.stderr if destination is None else destination
def wrapper(*args, **kwargs):
... # your code here
if fn is None:
def decorator(fn):
return functools.update_wrapper(wrapper, fn)
return decorator
else:
return functools.update_wrapper(wrapper, fn)
В Python 2.x это может быть эмулировано с приемами varargs:
def redirected_output(*fn,**options):
destination = options.pop('destination', sys.stderr)
if options:
raise TypeError("unsupported keyword arguments: %s" %
",".join(options.keys()))
def wrapper(*args, **kwargs):
... # your code here
if fn:
return functools.update_wrapper(wrapper, fn[0])
else:
def decorator(fn):
return functools.update_wrapper(wrapper, fn)
return decorator
Любая из этих версий позволила бы Вам писать код как это:
@redirected_output
def foo():
...
@redirected_output(destination="somewhere.log")
def bar():
...
Декоратора Python вызывают существенно другим способом в зависимости от того, даете ли Вы ему аргументы или нет. Художественное оформление на самом деле просто (синтаксически ограничено) выражение.
В Вашем первом примере:
@redirect_output("somewhere.log")
def foo():
....
функция redirect_output
вызвана с данным аргументом, который, как ожидают, возвратит функцию декоратора, которая саму вызвана с foo
как аргумент, который (наконец!), как ожидают, возвратит финал украшенная функция.
эквивалентный код похож на это:
def foo():
....
d = redirect_output("somewhere.log")
foo = d(foo)
эквивалентный код для Вашего второго примера похож:
def foo():
....
d = redirect_output
foo = d(foo)
, Таким образом, Вы можете делать то, что Вы хотели бы, но не полностью бесшовным способом:
import types
def redirect_output(arg):
def decorator(file, f):
def df(*args, **kwargs):
print 'redirecting to ', file
return f(*args, **kwargs)
return df
if type(arg) is types.FunctionType:
return decorator(sys.stderr, arg)
return lambda f: decorator(arg, f)
Это должно быть в порядке, если Вы не будете хотеть использовать функцию в качестве аргумента Вашему декоратору, в этом случае декоратор неправильно предположит, что это не имеет никаких аргументов. Это также перестанет работать, если это художественное оформление будет применено к другому художественному оформлению, которое не возвращает функциональный тип.
альтернативный метод должен только потребовать, чтобы функция декоратора всегда вызывалась, даже если это без аргументов. В этом случае Ваш второй пример был бы похож на это:
@redirect_output()
def foo():
....
код функции декоратора был бы похож на это:
def redirect_output(file = sys.stderr):
def decorator(file, f):
def df(*args, **kwargs):
print 'redirecting to ', file
return f(*args, **kwargs)
return df
return lambda f: decorator(file, f)
Необходимо обнаружить оба случая, например, с помощью типа первого аргумента, и соответственно возвратить любого обертка (при использовании без параметра) или декоратор (при использовании с аргументами).
from functools import wraps
import inspect
def redirect_output(fn_or_output):
def decorator(fn):
@wraps(fn)
def wrapper(*args, **args):
# Redirect output
try:
return fn(*args, **args)
finally:
# Restore output
return wrapper
if inspect.isfunction(fn_or_output):
# Called with no parameter
return decorator(fn_or_output)
else:
# Called with a parameter
return decorator
При использовании @redirect_output("output.log")
синтаксис, redirect_output
называют с отдельным аргументом "output.log"
, и он должен возвратить декоратора, принимающего, что функция украшена как аргумент. При использовании в качестве @redirect_output
это называют непосредственно с функцией, которая будет украшена как аргумент.
Или другими словами: @
синтаксис должен сопровождаться выражением, результатом которого является функция, принимающая, что функция украшена как собственный аргумент, и возвращающий украшенную функцию. Само выражение может быть вызовом функции, который имеет место с @redirect_output("output.log")
. Замысловатый, но истинный:-)
Вы попробовали споры ключевого слова со значениями по умолчанию? Что-то как
def decorate_something(foo=bar, baz=quux):
pass
Обычно можно дать параметры по умолчанию в Python...
def redirect_output(fn, output = stderr):
# whatever
Не уверенный, если это работает с декораторами также, все же. Я не знаю ни о какой причине, почему она не была бы.
Построение на ответе vartec:
imports sys
def redirect_output(func, output=None):
if output is None:
output = sys.stderr
if isinstance(output, basestring):
output = open(output, 'w') # etc...
# everything else...