python - Use cases for property vs. descriptor vs. __getattribute__ -
the question refers which 1 preferable used in use case, not technical background.
in python, can control access of attributes via property, descriptor, or magic methods. 1 pythonic in use case? of them seem have same effect (see examples below).
i looking answer like:
- property: should used in case of …
- descriptor: in case of … should used instead of property.
- magic method: use if ….
example
a use case attribute might not able set in __init__
method, example because object not present in database yet, @ later time. each time attribute accessed, should tried set , returned.
as example works copy&paste in python shell, there class wants present attribute second time asked it. so, 1 best way, or there different situations 1 of them preferable? here 3 ways implement it:
with property::
class contactbook(object): intents = 0 def __init__(self): self.__first_person = none def get_first_person(self): contactbook.intents += 1 if self.__first_person 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)
with __getattribute__
::
class contactbook(object): intents = 0 def __init__(self): self.first_person = none def __getattribute__(self, name): if name == 'first_person' \ , object.__getattribute__(self, name) 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
descriptor::
class firstperson(object): def __init__(self, value=none): self.value = none def __get__(self, instance, owner): if self.value 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()
each 1 of has behavior::
book = contactbook() print(book.first_person) # >>none print(book.first_person) # >>mr. first
basically, use simplest 1 can. speaking, order of complexity/heavy-duty-ness goes: regular attribute, property
, __getattr__
, __getattribute__
/descriptor. (__getattribute__
, custom descriptors both things won't need often.) leads simple rules of thumb:
- don't use
property
if normal attribute work. - don't write own descriptor if
property
work. - don't use
__getattr__
ifproperty
work. - don't use
__getattribute__
if__getattr__
work.
stated bit more specifically: use property customize handling of 1 or small set of attributes; use __getattr__
customize handling of attributes, or except small set; use __getattribute__
if hoping use __getattr__
doesn't quite work; write own descriptor class if doing complicated.
you use property
when have 1 or small set of attributes getting/setting want hook into. is, want things obj.prop
, obj.prop = 2
secretly call function write customize happens.
you use __getattr__
when want many attributes don't want define them individually, rather want customize whole attribute-access process whole. in other words, instead of hooking obj.prop1
, , obj.prop2
, etc., have many want able hook obj.<anything>
, , handle in general.
however, __getattr__
still won't let override happens attributes exist, lets hook in blanket handling use of attributes otherwise raise attributeerror. using __getattribute__
lets hook in handle everything, normal attributes have worked without messing __getattribute__
. because of this, using __getattribute__
has potential break basic behavior, should use if considered using __getattr__
, wasn't enough. can have noticeable performance impact. might instance need use __getattribute__
if you're wrapping class defines attributes, , want able wrap attributes in custom way, work usual in situations custom behavior in other situations.
finally, writing own descriptor advanced task. property
descriptor, , 95% of cases it's 1 you'll need. simple example of why might write own descriptor given here: basically, might if otherwise have write several property
s similar behavior; descriptor lets factor out common behavior avoid code repetition. custom descriptors used, instance, drive systems like django , sqlalchemy. if find writing @ level of complexity might need write custom descriptor.
in example, property
best choice. (not always) red flag if you're doing if name == 'somespecificname'
inside __getattribute__
. if need specially handle 1 specific name, can without stooping level of __getattribute__
. likewise, doesn't make sense write own descriptor if write __get__
have written in property's getter method.
Comments
Post a Comment