Python学习小记(5)---Magic Method
具体见The Python Language Reference
与Attribute相关的有
__get__
__set__
__getattribute__
__getattr__
__setattr__
__getitem__
__setitem__
Reference描述如下
3.3.2. Customizing attribute access
The following methods can be defined to customize the meaning of attribute access (use of, assignment to, or deletion of
x.name) for class instances.
object.__getattr__(self, name)Called when the default attribute access fails with an
AttributeError(either__getattribute__()raises anAttributeErrorbecause name is not an instance attribute or an attribute in the class tree forself; or__get__()of a name property raisesAttributeError). This method should either return the (computed) attribute value or raise anAttributeErrorexception.Note that if the attribute is found through the normal mechanism,
__getattr__()is not called. (This is an intentional asymmetry between__getattr__()and__setattr__().) This is done both for efficiency reasons and because otherwise__getattr__()would have no way to access other attributes of the instance. Note that at least for instance variables, you can fake total control by not inserting any values in the instance attribute dictionary (but instead inserting them in another object). See the__getattribute__()method below for a way to actually get total control over attribute access.
object.__getattribute__(self, name)Called unconditionally to implement attribute accesses for instances of the class. If the class also defines
__getattr__(), the latter will not be called unless__getattribute__()either calls it explicitly or raises anAttributeError. This method should return the (computed) attribute value or raise anAttributeErrorexception. In order to avoid infinite recursion in this method, its implementation should always call the base class method with the same name to access any attributes it needs, for example,object.__getattribute__(self, name).Note
This method may still be bypassed when looking up special methods as the result of implicit invocation via language syntax or built-in functions. See Special method lookup.
object.__setattr__(self, name, value)Called when an attribute assignment is attempted. This is called instead of the normal mechanism (i.e. store the value in the instance dictionary). name is the attribute name, value is the value to be assigned to it.
If
__setattr__()wants to assign to an instance attribute, it should call the base class method with the same name, for example,object.__setattr__(self, name, value).
object.__delattr__(self, name)Like
__setattr__()but for attribute deletion instead of assignment. This should only be implemented ifdelobj.nameis meaningful for the object.
object.__dir__(self)Called when
dir()is called on the object. A sequence must be returned.dir()converts the returned sequence to a list and sorts it.3.3.2.1. Customizing module attribute access
Special names
__getattr__and__dir__can be also used to customize access to module attributes. The__getattr__function at the module level should accept one argument which is the name of an attribute and return the computed value or raise anAttributeError. If an attribute is not found on a module object through the normal lookup, i.e.object.__getattribute__(), then__getattr__is searched in the module__dict__before raising anAttributeError. If found, it is called with the attribute name and the result is returned.The
__dir__function should accept no arguments, and return a list of strings that represents the names accessible on module. If present, this function overrides the standarddir()search on a module.For a more fine grained customization of the module behavior (setting attributes, properties, etc.), one can set the
__class__attribute of a module object to a subclass oftypes.ModuleType. For example:import sys
from types import ModuleType class VerboseModule(ModuleType):
def __repr__(self):
return f'Verbose {self.__name__}' def __setattr__(self, attr, value):
print(f'Setting {attr}...')
super().__setattr__(attr, value) sys.modules[__name__].__class__ = VerboseModuleNote
Defining module
__getattr__and setting module__class__only affect lookups made using the attribute access syntax – directly accessing the module globals (whether by code within the module, or via a reference to the module’s globals dictionary) is unaffected.Changed in version 3.5:
__class__module attribute is now writable.New in version 3.7:
__getattr__and__dir__module attributes.See also
- PEP 562 - Module __getattr__ and __dir__
- Describes the
__getattr__and__dir__functions on modules.3.3.2.2. Implementing Descriptors
The following methods only apply when an instance of the class containing the method (a so-called descriptorclass) appears in an owner class (the descriptor must be in either the owner’s class dictionary or in the class dictionary for one of its parents). In the examples below, “the attribute” refers to the attribute whose name is the key of the property in the owner class’
__dict__.
object.__get__(self, instance, owner)Called to get the attribute of the owner class (class attribute access) or of an instance of that class (instance attribute access). owner is always the owner class, while instance is the instance that the attribute was accessed through, or
Nonewhen the attribute is accessed through the owner. This method should return the (computed) attribute value or raise anAttributeErrorexception.
object.__set__(self, instance, value)Called to set the attribute on an instance instance of the owner class to a new value, value.
object.__delete__(self, instance)Called to delete the attribute on an instance instance of the owner class.
object.__set_name__(self, owner, name)Called at the time the owning class owner is created. The descriptor has been assigned to name.
New in version 3.6.
The attribute
__objclass__is interpreted by theinspectmodule as specifying the class where this object was defined (setting this appropriately can assist in runtime introspection of dynamic class attributes). For callables, it may indicate that an instance of the given type (or a subclass) is expected or required as the first positional argument (for example, CPython sets this attribute for unbound methods that are implemented in C).3.3.2.3. Invoking Descriptors
In general, a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol:
__get__(),__set__(), and__delete__(). If any of those methods are defined for an object, it is said to be a descriptor.The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance,
a.xhas a lookup chain starting witha.__dict__['x'], thentype(a).__dict__['x'], and continuing through the base classes oftype(a)excluding metaclasses.However, if the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined and how they were called.
The starting point for descriptor invocation is a binding,
a.x. How the arguments are assembled depends ona:
- Direct Call
- The simplest and least common call is when user code directly invokes a descriptor method:
x.__get__(a).- Instance Binding
- If binding to an object instance,
a.xis transformed into the call:type(a).__dict__['x'].__get__(a,type(a)).- Class Binding
- If binding to a class,
A.xis transformed into the call:A.__dict__['x'].__get__(None, A).- Super Binding
- If
ais an instance ofsuper, then the bindingsuper(B, obj).m()searchesobj.__class__.__mro__for the base classAimmediately precedingBand then invokes the descriptor with the call:A.__dict__['m'].__get__(obj, obj.__class__).For instance bindings, the precedence of descriptor invocation depends on the which descriptor methods are defined. A descriptor can define any combination of
__get__(),__set__()and__delete__(). If it does not define__get__(), then accessing the attribute will return the descriptor object itself unless there is a value in the object’s instance dictionary. If the descriptor defines__set__()and/or__delete__(), it is a data descriptor; if it defines neither, it is a non-data descriptor. Normally, data descriptors define both__get__()and__set__(), while non-data descriptors have just the__get__()method. Data descriptors with__set__()and__get__()defined always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances.Python methods (including
staticmethod()andclassmethod()) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire behaviors that differ from other instances of the same class.The
property()function is implemented as a data descriptor. Accordingly, instances cannot override the behavior of a property.3.3.2.4. __slots__
__slots__ allow us to explicitly declare data members (like properties) and deny the creation of __dict__ and __weakref__ (unless explicitly declared in __slots__ or available in a parent.)
The space saved over using __dict__ can be significant.
object.__slots__This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. __slots__ reserves space for the declared variables and prevents the automatic creation of __dict__ and __weakref__ for each instance.
3.3.2.4.1. Notes on using __slots__
- When inheriting from a class without __slots__, the __dict__ and __weakref__ attribute of the instances will always be accessible.
- Without a __dict__ variable, instances cannot be assigned new variables not listed in the __slots__definition. Attempts to assign to an unlisted variable name raises
AttributeError. If dynamic assignment of new variables is desired, then add'__dict__'to the sequence of strings in the __slots__ declaration.- Without a __weakref__ variable for each instance, classes defining __slots__ do not support weak references to its instances. If weak reference support is needed, then add
'__weakref__'to the sequence of strings in the __slots__ declaration.- __slots__ are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by __slots__; otherwise, the class attribute would overwrite the descriptor assignment.
- The action of a __slots__ declaration is not limited to the class where it is defined. __slots__ declared in parents are available in child classes. However, child subclasses will get a __dict__ and __weakref__unless they also define __slots__ (which should only contain names of any additional slots).
- If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly from the base class). This renders the meaning of the program undefined. In the future, a check may be added to prevent this.
- Nonempty __slots__ does not work for classes derived from “variable-length” built-in types such as
int,bytesandtuple.- Any non-string iterable may be assigned to __slots__. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key.
- __class__ assignment works only if both classes have the same __slots__.
- Multiple inheritance with multiple slotted parent classes can be used, but only one parent is allowed to have attributes created by slots (the other bases must have empty slot layouts) - violations raise
TypeError.
Python学习小记(5)---Magic Method的更多相关文章
- Python学习小记(4)---class
1.名称修改机制 大概是会对形如 __parm 的成员修改为 _classname__spam 9.6. Private Variables “Private” instance variables ...
- python学习小记
python HTTP请求示例: # coding=utf-8 # more materials: http://docs.python-requests.org/zh_CN/latest/user/ ...
- Python学习小记(3)---scope&namespace
首先,函数里面是可以访问外部变量的 #scope.py def scope_test(): spam = 'scope_test spam' def inner_scope_test(): spam ...
- Python学习小记(1)---import小记
在这种目录结构下,import fibo会实际导入fibo文件夹这个module λ tree /F 卷 Programs 的文件夹 PATH 列表 卷序列号为 BC56-3256 D:. │ fib ...
- Python学习小记(2)---[list, iterator, and, or, zip, dict.keys]
1.List行为 可以用 alist[:] 相当于 alist.copy() ,可以创建一个 alist 的 shallo copy,但是直接对 alist[:] 操作却会直接操作 alist 对象 ...
- python 学习小记之冒泡排序
lst =[11,22,44,2,1,5,7,8,3] for i in range(len(lst)): i = 0 while i < len(lst)-1: ...
- Python魔术方法-Magic Method
介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...
- Python:Python学习总结
Python:Python学习总结 背景 PHP的$和->让人输入的手疼(PHP确实非常简洁和强大,适合WEB编程),Ruby的#.@.@@也好不到哪里(OO人员最该学习的一门语言). Pyth ...
- Magic Method
Python 的 Magic Method 在 Python 中,所有以 "__" 双下划线包起来的方法,都统称为"魔术方法".比如我们接触最多的 __init ...
随机推荐
- AVR单片机教程——串口接收
本文隶属于AVR单片机教程系列. 上一讲中,我们实现了单片机开发板向电脑传输数据.在这一讲中,我们将通过电脑向单片机发送指令,让单片机根据指令控制LED.这一次,两端的TX与RX需要交叉连接,单片 ...
- Scrapy解析器xpath
一.使用xpath 不在scrapy框架中通过response from scrapy.http import HtmlResponse HtmlResponse->TextResponse-& ...
- MySql查看修改l时区
# 查看时区 show variables like '%time_zone%'; # 设置全局 set global time_zone='+8:00'; # 设置当前会话 set time_zo ...
- python面向对象(一切皆对象)
使用面向对象的思想设计一个乌龟的角色: 表面特征:绿色.有4条腿.重10kg.有外壳等等 行为特征:爬.吃.睡觉.将头和四肢缩到壳里等等 class tortoise: bodycolor = &qu ...
- Wordpress4.9.6 任意文件删除漏洞复现分析
第一章 漏洞简介及危害分析 1.1漏洞介绍 WordPress可以说是当今最受欢迎的(我想说没有之一)基于PHP的开源CMS,其目前的全球用户高达数百万,并拥有超过4600万次的超高下载量.它是一个开 ...
- [mvc>actionResult] 封装一个操作方法的结果并用于代表该操作方法执行框架级操作
- 前端 network
控制台 :https://blog.csdn.net/m0_37724356/article/details/79884006 原文链接:https://segmentfault.com/a/1190 ...
- java泛型梳理
java泛型梳理 概述 泛型,即参数化类型,是在JDK1.5之后才开始引入的. 所谓参数化类型是指所操作的数据类型在定义时被定义为一个参数,然后在使用时传入具体的类型. 这种参数类型可以用在类,接口, ...
- linux--->ab测试工具使用
ab测试工具使用 ab简介 是apache自带的压力测试工具.其原理是ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问.它的测试目标是基于URL的,因此,它既可以用来测试ap ...
- Python变量、方法、类的命名规则
1. 变量命名总结: - 1.单下划线开头变量:protected - 2.双下划线开头变量:private - 3.双下划线开头,双下划线结尾:系统内置变量 2. 函数命名总结: - 1.私有方法: ...