_stream) popen()返回了一个_wrap_close对象,而后者仅仅是一个 Iterable,而不是 Iterator(没有定义__next__())。...然而,_wrap_close却定义了__getattr__()魔法方法,这样所有其他找不到的属性、方法就会传递给self._stream对象,而这个对象有__next__()方法。这就解释了为什么r....下面这段是额外的思考,可能比较绕: 再回头去看最开始的例子,这个问题之所以奇怪,是因为它用了__getattr__()让实例获得了并不存在于类中的属性。也就是说,原来的类并没有获得这些额外的属性。...明明Foo能获取到__next__()属性,看来(Py_TYPE(obj)->tp_iternext并不会触发__getattr__。...我用 Python 的时间不可谓不短,也自认对 Python 的语言特性比较了解了,但 Python 却总能时不时让我意外一下,这是什么情况?
函数与方法 内建函数: getattr(object,name[,degault]) 通过name返回object的属性值,当属性不存在,将使用default返回,如果没有default,则抛出AttributeError...hasattr(object,name) 判断对象是否有这个名字的属性,name必须为字符串 反射相关的魔术方法 __getattr__() 一个类的属性会按照继承关系找,如果找不到,就会执行__getattr...__()方法,如果没有这个方法,就会抛出AttributeError异常表示找不到属性。...值将作为属性查找的结果 如果抛出AttributeError异常,则会直接调用__gutattr__方法,因为表述属性没有找到。...一般不使用该方法 魔术方法 __getattr__() 当通过搜索实例、实例的类及祖先类查不到属性,就会调用此方法 __setattr__() 通过.访问实例的属性,进行增加,修改都要调用它 __delattr
,我们再思考一下,如果只定义了 __str__ 或 __repr__ 其中一个,那会是什么结果?...只定义 __str__,但没有定义 __repr__: # coding: utf8 class Person(object): def __init__(self, name, age):...p2 = Person() p2.age = -1 # __setattr__中引发ValueError 我们仔细看一下这个例子,我已经添加好了详细的注释。...__getattr__ 再来看 __getattr__,由于我们在 __setattr__ 中忽略了对 gender 属性的赋值,所以当访问这个不存在的属性时,会调用 __getattr__ 方法,在这个方法中返回了默认值...__getattr__ 只针对属性访问,而__getattribute__ 不仅针对所有属性访问,还包括方法调用 在上面的例子,虽然我们没有定义 money 属性和 hello 方法,但是在 __getattribute
Python中提供了一些魔术方法来控制对象属性的访问,赋值,删除过程。...属性访问魔术方法 __getattr__(self, item) __getattribute__(self, item) 其中__getattr__只有在属性不存在时会被调用,__getattribute...属性赋值魔术方法 __setattr__(self, key, value) 给对象属性赋值或者添加新属性时会被调用。...__ raise AttributeError(item + "属性不存在") AttributeError: age属性不存在 案例中__setattr__方法控制添加属性和给属性赋值的过程,...__dict__的方式来访问或修改属性,这种方式看上去可行,但是存在一个问题,因为self.__dict__本身也是对象的属性(只是这个属性比较特殊,它存放了对象的其它属性),所以每次访问self.
1.1.propety动态属性 在面向对象编程中,我们一般把名词性的东西映射成属性,动词性的东西映射成方法。在python中他们对应的分别是属性self.xxx和类方法。...如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常) (1)调用一个不存在的属性 class User:..._getattr__是在查找不到属性的时候调用 def __getattr__(self, item): return self.info[item] if __name__...int类型 #属性描述符 import numbers #只要一个类实现了下面三种魔法函数中的一种,这个类就是属性描述符 class IntField: def __get__(self,...) 运行结果:没有调用init方法 ?
回忆一下,我们开发时,一般把「行为」叫做什么?是的,「行为」一般指的是一个方法。 所以我们也可以把「描述符」理解为:对象的属性不再是一个具体的值,而是交给了一个方法去定义。...中,都有一个统一的调用逻辑: 先调用 __getattribute__ 尝试获得结果 如果没有结果,调用 __getattr__ 用代码表示就是下面这样: def getattr_hook(obj,...如果类中也没有这个属性,抛出 AttributeError 异常 写成代码就是下面这样: # 获取一个对象的属性 def __getattribute__(obj, name): null =...# 抛出 AttributeError 会触发调用 __getattr__ raise AttributeError(name) 如果不好理解,你最好写一个程序测试一下,观察各种情况下的属性的查找顺序...在这里我用描述符实现了一个属性校验器,你可以参考这个例子,在类似的场景中去使用它。
lambda: 25 只是调用方式要变为: >>> s.age() 25 注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。...要让class只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误: class Student(object): def __getattr__(self, attr...如果你把对象看成函数,那么函数本身其实也可以在运行期动态创建出来,因为类的实例都是运行期创建出来的,这么一来,我们就模糊了对象和函数的界限。 如何判断一个对象是否能被调用?...测试一下MyList是否可以调用add()方法: >>> L = MyList() >>> L.add(1) >> L [1] 而普通的list没有add()方法: >>> L2 = list() >>...实现了save()方法,把一个实例保存到数据库中。因为有表名,属性到字段的映射和属性值的集合,就可以构造出INSERT语句。
__new__ 类方法创建实例对象,__init__ 实例方法初始化实例对象。...__new__(cls, *arg, **kwargs), *arg, **kwargs 添加应用__init__一致, super() 中的参数要不2个,要不没有 class A(object):...__get__, __getattr__, __getattribute__ 的区别 均是访问属性的方法,注意是属性 __getattr__(self, name) 当访问属性无法找到时,默认异常,可以自定义其返回值或者...AttributeError 异常 __getattribute__(self, name): 2.7 在新式类中引入,如果定义,则无条件执行,如果实行不存在时,也不执行 __getattr__(相当于被屏蔽掉...) __get__ (self, instance, owner) : 如果class定义了它,则这个class就可以称为descriptor。
__name__, attr_name=name) raise AttributeError(msg) super()....__setattr__(name, value) # 其他name可以赋值 值得说明的是,__getattr__的机制是:对my_obj.x表达式,Python会检查my_obj实例有没有名为x的属性...,如果有就直接返回,不调用__getattr__方法;如果没有,到my_obj....__class__中查找,如果还没有,才调用__getattr__方法。...,因为赋值后Vector新增了一个x属性,值为10,对v.x表达式来说,直接就返回了这个值,不会走我们自定义的__getattr__方法,也就没办法拿到v[0]的值。
raise AttributeError,attrname ... >>> X=empty() >>> X.age 40 这里,empty类和其实例X本身并没有属性。...所以对X.age的存取会转换至__getattr__方法,self则赋值为实例(X), 而attrname则赋值为未定义的属性名称字符串("age"),这个类传回一个实际值作为X.age点号表达式的结果...2、属性名称:对象命名空间 点号的属性名称指的是特定对象的属性,并且遵守模块和类的规则。就类和实例对象而言,引用规则增加了继承搜索这个流程。...继承树的搜索只发生在属性引用时,而不是属性的赋值运算时 引用(object.X) 就基于类的对象而言,会在对象内搜索属性名X,然后是其上所有可读取的类(使用继承搜索流程).对于不是基于类的对象而言...3、命名空间:赋值将变量名分类 在Python中,赋值变量名的场所相当重要:这完全决定了变量名所在作用域或对象。一下实例总结了命名空间的概念。
__dir__())) 上例通过属性字典__dict__来访问对象的属性,本质上就是利用反射的能力,但是上面的例子中,访问的方式不优雅,Python提供了内置的函数 内建函数意义getattr(object...,name[,default])通过name返回object的属性值,当属性不存在,将属性不存在,将使用default返回,如果没有default,则抛出AttributeError,name必须是字符串...,如果找不到,就会执行__getattr__()方法,如果没有这个方法,就会抛出AttributeError异常标识找不到属性 查找属性顺序为: instance__dict__---->instance.class.dict...__dict__) print(Point.z) 实例的所有的属性访问,第一个都会调用__getattribute__方法,它阻止了属性的查找,该方法应该返回值或者抛出一个AttributeError...异常 它的return值将作为属性查找的结果如果抛出AttributeError异常,则会直接调用__getattr__方法,因为属性没有找到 __getattribute__方法中为了避免在该方法中无线递归
_className__attrName (对象名._类名__私有属性名)进行访问 class A: __secret = 123 a = A() a..../all 二者都是访问属性的方法,不同的是所有通过实例访问属性都会触发 __getattribute__ 方法,而当访问的属性不存在时,会继续触发 __getattr__,也就是说 __getattribute...__ 一定会在 __getattr__ 之前触发,当 __getattribute__ 有返回值时就不会再触发 __getattr__ __getattr__(self, name) self:函数中固定第一个参数...,在没有对应属性时,将触发 AttributeError object....__base__ # __bases__ 可用于查看一个类的全部父类, 但只能向上寻找一层 class A: pass class B(A):
需要开启更大的内存区域,将原始的属性赋值过去 问题:如果开启的容量太大(为了效率牺牲了空间),将造成内存的浪费 解决方案:在创建对象是告诉系统这个对象只有哪些属性,也就是固定了对象的属性数量,这样就可任意要多少开多少...时将导致这个类的对象不再添加__slots__定义之外的属性 __getattr__ __setattr__ __delattr__ 及点语法原理 __getattr__ 用 .访问属性时,如果属性不存在...语法的原理 __getattribute__ 该函数也是用来获取属性 在获取属性时如果存在__getattribute__则先执行该函数,如果没有拿到属性则继续调用__getattr__函数,如果拿到了则直接返回...__dict__.pop(item) a = A() a.name = 'jack' # __setattr__ print(a.name) # 这个属性存在,就没有调用 __getattr__...# __delattr__ # name print(b.name) # b没有name这个属性了,就触发了 __getattr__ # __getattr__ # None # b没有name
01.控制属性存取 控制属性存取 Python中定义了一些用于属性存取的特殊方法: 方法名称 使用 描述 __delattr__(self, name) del x.n 删除对象x的属性 __dir_..._(self) dir(x) 返回x的属性名列表 __getattr__(self, name) v = x.n 返回对象x的n属性值 __getattribute__(self, name) v =...x.n 返回对象x的n属性值 __setattr__(self, name) x.n = v 将对象x的n属性名值设为v __getattr__ 与 __getattribute__ 的主要区别: _...__getattr__() 在以下情况下调用: 属性不在实例的dict中; 属性不在其基类以及祖先类的dict 中; 触发AttributeError 异常时(不仅仅是get_attribute() 引发的异常...下面定义了一个简单的 “常数” 类,可以正常的设置任意属性,但如果想要去改变或者删除该属性,则会产生异常。
上面的例子中类 Sample 只有两个方法,下面让我们实例化一下: >>> s = Sample() >>> s.x hello getattr s.x 这个实例属性本来是不存在的,但是由于类中有了 _..._getattr__(self,name) 方法,当发现属性 x 不存在于对象的 __dict__ 中时,就调用了 __getattr__,也就是所谓的「拦截成员」。...如果再调用这个属性的话,会成为下面这样: >>> s.x 7 出现这种结果的原因是它已经存在于对象的 __dict__ 中了。 看了上面的两个,你是不是觉得上面的方法很有魔力呢?...: (3, 4) 30 40 我们可以看到,除了类的写法变了以外,调用的方式没有变,结果也没有变。...至此,不知道你发现了没有,我们使用了很多以双下划线开头和结尾的属性和方法,比如 __init__ 等。
' 由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。...但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。 有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的 Python 程序员来说,这是必须要做到的!...lambda: 25 只是调用方式要变为: >>> s.age() 25 注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。...要让 class 只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误: class Student(object): def __getattr__(self, attr...测试一下MyList是否可以调用add()方法: >>> L = MyList() >>> L.add(1) >> L [1] 而普通的list没有add()方法: >>> L2 = list() >>
前言 当实例对象调用一个不存在的属性时,系统通常会报错,那有啥办法避免这种现象么,或者说自定义报错信息,答案是肯定的,我们可以通过定义__getattr__(self,name)魔法方法来实现。...当实例对象调用不存在的属性时,如果在类中没重载__getattr__(self,name)方法,则会抛出AttributeError异常,如下所示: >>> class Animal(): ......: 'Animal' object has no attribute 'a' 而当我们重载了__getattr__(self,name)方法,一旦属性查找失败,就会调用__getattr__(self...这边也来说下调用__getattr__的详细过程: 1.在对象的实例属性中寻找,找不到执行下一步2.在的类中查找类属性,找不到执行下一步3.在对象的继承链上寻找,找不到执行下一步4.调用__getattr...__ 方法,如果用户没有定义或者还是找不到,抛出AttributeError异常,属性查找失败!
例如,读取属性(具体来说,是实例中访问类中定义的属性)时,如果它关联的是一个实现了__get__的对象,将不会返回这个对象,而是调用方法__get__并将其结果返回。...__getattribute__(self, name):在属性被访问时自动调用(只适用于新式类)。 __getattr__(self, name):在属性被访问而对象没有这样的属性时自动调用。...仅当没有找到指定的属性时,才会调用方法__getattr__。这意味着如果指定的名称不是size,这个方法将引发AttributeError异常。...有些人可能之前只使用for循环迭代过序列和字典,但实际上也可迭代其他对象:实现了方法__iter__的对象。...---- 注意 更正规的定义是,实现了方法__iter__的对象是可迭代的,而实现了方法__next__的对象是迭代器。 ---- 首先,创建一个Fibs对象。
对于一般的实例对象,__dict__ 会返回一个保存包含所有实例属性的独立的 dict 实例对象,对 __getattribute__ 的调用首先会访问这个 dict,并获取相应的实例属性 (这个调用会在通过描述器协议访问...class 属性之前,也会在调用 __getattr__ 之前)。...这个特殊的 proxy 对象允许你,获取那些定义在 class 而不是 class 的基类中的的属性。...前两个描述器可能会因为定义了 __slots__ 而消失,没有 __dict__ and __weakref__ 属性,反而会有每一个定义在 __slots__ 的属性。...__getattr__(*args, **kwargs) return origin except AttributeError as e:
在Adder类的实例化过程中,我们将数字5传递给了构造方法__init,从而初始化了Adder对象的属性n。...然后,我们创建了一个名为add5的Adder对象,并使用()运算符将数字3传递给了add5对象。...这时,Python会自动调用add5对象的__call__方法,将数字3作为参数传递给__call__方法,并返回n + x的结果,即8。...当我们使用点运算符访问一个对象的属性时,如果该属性不存在,Python会自动调用该对象的__getattr__方法,并将属性名称作为参数传递给__getattr__方法。...如果属性名称不为'x'或者'y',则会抛出AttributeError异常。因此,我们可以使用__getattr__方法为对象动态添加属性,从而实现灵活的对象属性访问行为。
领取专属 10元无门槛券
手把手带您无忧上云