Iod*_*nas 14 python properties descriptor getattribute
问题是哪一个最好用于哪个用例,而不是技术背景.
在python中,您可以通过属性,描述符或魔术方法来控制属性的访问.哪个用例最具pythonic?所有这些似乎都具有相同的效果(参见下面的例子).
我正在寻找一个答案:
例
用例将是可能无法在__init__
方法中设置的属性,例如因为该对象尚未存在于数据库中,而是在稍后的时间.每次访问该属性时,都应尝试设置并返回该属性.
作为在Python shell中使用Copy&Paste的示例,有一个类只想在第二次询问它时才显示其属性.那么,哪一个是最好的方式,还是有不同的情况,其中一个更好?以下是实现它的三种方法:
随着物业 ::
class ContactBook(object):
intents = 0
def __init__(self):
self.__first_person = None
def get_first_person(self):
ContactBook.intents += 1
if self.__first_person is None:
if ContactBook.intents > 1:
value = 'Mr. First'
self.__first_person = value
else:
return None
return self.__first_person
def set_first_person(self, value):
self.__first_person = value
first_person = property(get_first_person, set_first_person)
Run Code Online (Sandbox Code Playgroud)
带__getattribute__
::
class ContactBook(object):
intents = 0
def __init__(self):
self.first_person = None
def __getattribute__(self, name):
if name == 'first_person' \
and object.__getattribute__(self, name) is None:
ContactBook.intents += 1
if ContactBook.intents > 1:
value = 'Mr. First'
self.first_person = value
else:
value = None
else:
value = object.__getattribute__(self, name)
return value
Run Code Online (Sandbox Code Playgroud)
描述符 ::
class FirstPerson(object):
def __init__(self, value=None):
self.value = None
def __get__(self, instance, owner):
if self.value is None:
ContactBook.intents += 1
if ContactBook.intents > 1:
self.value = 'Mr. First'
else:
return None
return self.value
class ContactBook(object):
intents = 0
first_person = FirstPerson()
Run Code Online (Sandbox Code Playgroud)
每一个都有这种行为::
book = ContactBook()
print(book.first_person)
# >>None
print(book.first_person)
# >>Mr. First
Run Code Online (Sandbox Code Playgroud)
Bre*_*arn 19
基本上,使用最简单的一个.大致说来,复杂性/重型岬的顺序云:常规属性property
,__getattr__
,__getattribute__
/描述符.(__getattribute__
和自定义描述符都是你可能不需要经常做的事情.)这导致了一些简单的经验法则:
property
如果普通属性不起作用,请不要使用.property
可行的话,不要编写自己的描述符.__getattr__
如果一个property
会工作,请不要使用.__getattribute__
if if __getattr__
work.更具体地说明:使用属性来自定义一个或一小组属性的处理; 用于__getattr__
自定义所有属性的处理,或除了一小组之外的所有属性; 使用,__getattribute__
如果你希望使用,__getattr__
但它不起作用; 如果您正在做一些非常复杂的事情,请编写自己的描述符类
property
如果您有一个或一小组要获取/设置的属性,则使用a .也就是说,你想要obj.prop
和你obj.prop = 2
秘密调用你编写的函数来定制发生的事情.
你会使用__getattr__
,当你想要做的是为你实际上并不希望单独定义所有的这么多的属性,而是要自定义的全属性的访问过程作为一个整体.换句话说,而不是钩住obj.prop1
,和obj.prop2
等,你有这么多,你希望能够挂接到obj.<anything>
,并处理一般.
但是,__getattr__
仍然不会让你覆盖真正存在的属性所发生的事情,它只是让你用一个毯子处理来使用任何可能会引发AttributeError的属性.使用__getattribute__
允许您挂钩处理所有内容,甚至是可以正常工作而不会搞砸的普通属性__getattribute__
.因此,使用__getattribute__
有可能破坏相当基本的行为,所以你应该只在你考虑使用__getattr__
它时才使用它,这是不够的.它还可以产生明显的性能影响.例如,__getattribute__
如果要包装定义某些属性的类,并且希望能够以自定义方式包装这些属性,则可能需要使用它们,以便它们在某些情况下照常工作,但在其他情况下获取自定义行为.
最后,我想说编写自己的描述符是一项相当高级的任务. property
是一个描述符,大概95%的情况下它是你唯一需要的.你为什么会写自己的描述符一个很好的简单的例子给出了这里:基本上,你可以做,如果你本来有写一些property
s的类似的行为; 描述符允许您分解常见行为以避免代码重复.例如,自定义描述符用于驱动像Django和SQLAlchemy这样的系统.如果您发现自己在复杂程度上写了一些内容,则可能需要编写自定义描述符.
在您的示例中,property
将是最佳选择.如果你在if name == 'somespecificname'
里面做的话,它通常(并不总是)是一面红旗__getattribute__
.如果您只需要专门处理一个特定的名称,您可以在不弯腰到达的情况下执行此操作__getattribute__
.同样地,如果您为其编写的所有内容__get__
都是您可以在属性的getter方法中编写的,那么编写自己的描述符是没有意义的.
归档时间: |
|
查看次数: |
2097 次 |
最近记录: |