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
propertyif normal attribute work. - don't write own descriptor if
propertywork. - don't use
__getattr__ifpropertywork. - 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 propertys 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