Dekore edilmiş fonksiyonların korunması imzaları
Bir şey çok genel bir dekoratör yazdım sanırım. Örneğin, belirli bir türü için tüm değişkenleri dönüştürmek, günlük gerçekleştirmek, memoization, vb uygulayabilir.
İşte bir örnek:
def args_as_ints(f): def g(*args, **kwargs): args = [int(x) for x in args] kwargs = dict((k, int(v)) for k, v in kwargs.items()) return f(*args, **kwargs) return g @args_as_ints def funny_function(x, y, z=3): """Computes x*y 2*z""" return x*y 2*z >>> funny_function("3", 4.0, z="5") 22
Şimdiye kadar her şey güzel. Bir sorun, ancak var. Süslü işlevi özgün işlevi belgelerine korumaz:
>>> help(funny_function) Help on function g in module __main__: g(*args, **kwargs)
Neyse ki, bir çözüm vardır:
def args_as_ints(f): def g(*args, **kwargs): args = [int(x) for x in args] kwargs = dict((k, int(v)) for k, v in kwargs.items()) return f(*args, **kwargs) g.__name__ = f.__name__ g.__doc__ = f.__doc__ return g @args_as_ints def funny_function(x, y, z=3): """Computes x*y 2*z""" return x*y 2*z
Bu sefer, işlev adı ve belgeler doğru
>>> help(funny_function) Help on function funny_function in module __main__: funny_function(*args, **kwargs) Computes x*y 2*z
Ama orada hala bir sorun: işlev imzası yanlış. Bilgiler ", ***kwargs besten" gelecek için bir işe yaramaz.
Ne? Basit ama mükemmel olmayan iki geçici çözüm düşünebilirsiniz:
1 -- Fibonacci sayıları doğru imza Vardır:
def funny_function(x, y, z=3): """funny_function(x, y, z=3) -- computes x*y 2*z""" return x*y 2*z
Bu tekrarından dolayı kötü. İmza hala düzgün bir şekilde otomatik olarak oluşturulan belgelerinde gösterilecektir. Kolay işlevi güncelleme ve Fibonacci sayıları değişen, ya da bir yazım hatası yapmak için unutmak. [ . ben^>Ve evet, Fibonacci sayıları zaten işlev gövdesi çoğaltan bu gerçeğin farkındayım. Lütfen bu; funny_function rasgele bir örnek, sadece görmezden.]
2 -- bir dekoratör kullanın, ya da her özel imza için özel amaçlı bir dekoratör kullanın:
def funny_functions_decorator(f): def g(x, y, z=3): return f(int(x), int(y), z=int(z)) g.__name__ = f.__name__ g.__doc__ = f.__doc__ return g
Bu aynı imza olan fonksiyonları bir dizi için gayet iyi çalışıyor, ama genelde işe yaramaz. Başlangıçta da söylediğim gibi, dekoratörler tamamen kullanabilmek için jenerik olmak istiyorum.
Tamamen genel ve otomatik bir çözüm arıyorum.
Soru şu: orada bir şekilde oluşturulduktan sonra? dekore işlev imzası düzenlemek için.
Aksi takdirde, işlev imzası ayıklar ve bu bilgileri kullanan bir dekoratör yerine "*kwargs, **kwargs" dekore edilmiş fonksiyon inşa? yazabilir miyim Bu nasıl bilgi elde edebilirim? Nasıl dekore işlevi exec ile inşa etmeli miyim?
Başka yaklaşımlar?
CEVAP
decorator modülü yükleyin:
$ pip install decorator
Uyum
args_as_ints()
tanımı:import decorator @decorator.decorator def args_as_ints(f, *args, **kwargs): args = [int(x) for x in args] kwargs = dict((k, int(v)) for k, v in kwargs.items()) return f(*args, **kwargs) @args_as_ints def funny_function(x, y, z=3): """Computes x*y 2*z""" return x*y 2*z print funny_function("3", 4.0, z="5") # 22 help(funny_function) # Help on function funny_function in module __main__: # # funny_function(x, y, z=3) # Computes x*y 2*z
Python 3.4
functools.wraps()
from stdlib Python 3.4 beri: imza korur
import functools
def args_as_ints(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return func(*args, **kwargs)
return wrapper
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y 2*z"""
return x*y 2*z
print(funny_function("3", 4.0, z="5"))
# 22
help(funny_function)
# Help on function funny_function in module __main__:
#
# funny_function(x, y, z=3)
# Computes x*y 2*z
functools.wraps()
imzası var korumaz at least since Python 2.5 ama kullanılabilir:
help(funny_function)
# Help on function funny_function in module __main__:
#
# funny_function(*args, **kwargs)
# Computes x*y 2*z
Dikkat: *args, **kwargs
yerine x, y, z=3
.
İtfa edilmiş, sürekli R listesine bir ...
Mac kullanıcı ve alma UYARI: LibXML sü...
Nasıl piyasa verileri 7.3 milyar satır...
Neden C ve C derleyicileri onlar'...
Nasıl Node.js zaman uyumsuz fonksiyonl...