我最近在阅读有关属性(即property
装饰器)的文章,得出的结论是,我真的不喜欢它在python中的实现方式。好吧,我知道它不是语言本身的内部部分(例如,它没有像C#那样内置在语言中),但是我真的认为他们可以更好地实现它(即使只有装饰器)。我想对我认为应该实施的方式进行概念验证,但是我遇到了一点障碍(尽管没有什么可以克服的...)。
这就是我的想法:假设我们有一个Person
带有属性的类name
。我定义属性的方式如下所示:
class Person():
def __init__(self, name, age):
self._name = name
self._age = age
@my_property
def name(self):
def getter(self):
return self._name
def setter(self, value):
self._name = value
def deleter(self):
del self._name
return getter, setter, deleter
我们的装饰器my_property
定义如下:
def my_property(f):
d = {g.__name__: g for g in f(None)}
p = property(d.get('getter'), d.get('setter'), d.get('deleter'))
return p
现在,这很好用,但是我真的很想通过允许用户不显式添加代码行来改进它return getter, setter, deleter
。相反,我希望装饰器将该行添加到f
传递给它的函数中(在我们的示例中为name
方法)。我猜我将不得不处理f
(即f.__code__
)的代码对象,但是我无法弄清楚如何完成我想要的工作。
我关于属性外观的方式与属性的C#语法非常相似。我相信同一字段的getter,setter和deleteer应该在某些代码块中分组在一起(在我的情况下,我选择了一个函数定义),并且不要在(最多)3个单独的方法中遍及整个类(即使它们具有相同的名称,它们仍然在语法上是分隔开的。)...此外,我认为它是现在定义的方式-首先由property
装饰器将getter声明为属性,然后使用getter的名称进行装饰设置器和删除器非常难看。但这只是我:)
更新
接受@User的答案后,我使用他的想法从包装方法的代码对象内部获取代码对象,重新实现了我的属性装饰器。这是我的新实现,仍然只是一个原型(我相信可以进一步改进)。我决定property
用我的新装饰器(使用原始property
装饰器)将内置装饰器遮盖起来,但是可以将其命名为任何内容...总的来说,我认为这很酷,我希望Python有一个property
可以使用的关键字定义属性,而不是使用方法定义或类定义(如@User在其答案中建议的那样)。
def property(f, property=property):
from types import CodeType, FunctionType
d = {code.co_name: FunctionType(code, f.__globals__)
for code in f.__code__.co_consts
if type(code) is CodeType}
return property(d.get('getter'), d.get('setter'), d.get('deleter'), f.__doc__)
class Person():
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name():
def getter(self):
return self._name
def setter(self, value):
self._name = value
def deleter(self):
del self._name
>>> p1 = Person('Name', 25)
>>> p1.name
'Name'
>>> p1.name = "New Name"
>>> p1.name
'New Name'
现在,您可以使其更漂亮:
>>> def dec(f):
import types
codes = []
for code in f.__code__.co_consts:
if isinstance(code, types.CodeType):
codes.append(code)
getter = types.FunctionType(codes[0], f.__globals__)
setter = types.FunctionType(codes[1], f.__globals__)
detter = types.FunctionType(codes[2], f.__globals__)
return property(getter, setter, detter, f.__doc__)
>>> class X:
@dec
def f():
def g(*args):
print('get', args)
def h(*args):
print('set', args)
def j(*args):
print('del', args)
>>> X().f
get (<__main__.X object at 0x02DFD870>,)
>>> X().f = 1
set (<__main__.X object at 0x02E13750>, 1)
>>> del X().f
del (<__main__.X object at 0x02DFD870>,)
我对您的想法感兴趣。
但是也许使用类装饰器甚至更好
@dec
class attribute:
# ... functions
也许还有with语句:
with makeProperty:
# ... functions
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句