首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从 Python 的魔法方法说开去

_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 却总能时不时让我意外一下,这是什么情况?

16720

Python中反射和描述器总结

函数与方法 内建函数: getattr(object,name[,degault])  通过name返回object的属性值,当属性不存在,将使用default返回,如果没有default,则抛出AttributeError...hasattr(object,name)  判断对象是否有这个名字的属性,name必须为字符串 反射相关的魔术方法 __getattr__() 一个类的属性会按照继承关系找,如果找不到,就会执行__getattr...__()方法,如果没有这个方法,就会抛出AttributeError异常表示找不到属性。...值将作为属性查找的结果 如果抛出AttributeError异常,则会直接调用__gutattr__方法,因为表述属性没有找到。...一般不使用该方法 魔术方法 __getattr__() 当通过搜索实例、实例的类及祖先类查不到属性,就会调用此方法 __setattr__() 通过.访问实例的属性,进行增加,修改都要调用它 __delattr

92820
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Python进阶——如何正确使用魔法方法?(上)

    ,我们再思考一下,如果只定义了 __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

    71332

    Python自学成才之路 魔术方法之属性访问控制

    Python中提供了一些魔术方法来控制对象属性的访问,赋值,删除过程。...属性访问魔术方法 __getattr__(self, item) __getattribute__(self, item) 其中__getattr__只有在属性不存在时会被调用,__getattribute...属性赋值魔术方法 __setattr__(self, key, value) 给对象属性赋值或者添加新属性时会被调用。...__ raise AttributeError(item + "属性不存在") AttributeError: age属性不存在 案例中__setattr__方法控制添加属性和给属性赋值的过程,...__dict__的方式来访问或修改属性,这种方式看上去可行,但是存在一个问题,因为self.__dict__本身也是对象的属性(只是这个属性比较特殊,它存放了对象的其它属性),所以每次访问self.

    54520

    Python进阶——什么是描述符?

    回忆一下,我们开发时,一般把「行为」叫做什么?是的,「行为」一般指的是一个方法。 所以我们也可以把「描述符」理解为:对象的属性不再是一个具体的值,而是交给了一个方法去定义。...中,都有一个统一的调用逻辑: 先调用 __getattribute__ 尝试获得结果 如果没有结果,调用 __getattr__ 用代码表示就是下面这样: def getattr_hook(obj,...如果类中也没有这个属性,抛出 AttributeError 异常 写成代码就是下面这样: # 获取一个对象的属性 def __getattribute__(obj, name): null =...# 抛出 AttributeError 会触发调用 __getattr__ raise AttributeError(name) 如果不好理解,你最好写一个程序测试一下,观察各种情况下的属性的查找顺序...在这里我用描述符实现了一个属性校验器,你可以参考这个例子,在类似的场景中去使用它。

    38030

    10-面向对象2

    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语句。

    1.5K20

    Python学习笔记整理(十五)类的编写

    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中,赋值变量名的场所相当重要:这完全决定了变量名所在作用域或对象。一下实例总结了命名空间的概念。

    90910

    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__方法中为了避免在该方法中无线递归

    87300

    python面向对象的多态-类相关内置函数-类内置魔法函数-迭代器协议-上下文管理-04

    需要开启更大的内存区域,将原始的属性赋值过去 问题:如果开启的容量太大(为了效率牺牲了空间),将造成内存的浪费 解决方案:在创建对象是告诉系统这个对象只有哪些属性,也就是固定了对象的属性数量,这样就可任意要多少开多少...时将导致这个类的对象不再添加__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

    68440

    Python指南:高级程序设计之面向对象程序设计进阶

    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() 引发的异常...下面定义了一个简单的 “常数” 类,可以正常的设置任意属性,但如果想要去改变或者删除该属性,则会产生异常。

    88620

    Python 黑魔法之属性拦截

    上面的例子中类 Sample 只有两个方法,下面让我们实例化一下: >>> s = Sample() >>> s.x hello getattr s.x 这个实例属性本来是不存在的,但是由于类中有了 _..._getattr__(self,name) 方法,当发现属性 x 不存在于对象的 __dict__ 中时,就调用了 __getattr__,也就是所谓的「拦截成员」。...如果再调用这个属性的话,会成为下面这样: >>> s.x 7 出现这种结果的原因是它已经存在于对象的 __dict__ 中了。 看了上面的两个,你是不是觉得上面的方法很有魔力呢?...: (3, 4) 30 40 我们可以看到,除了类的写法变了以外,调用的方式没有变,结果也没有变。...至此,不知道你发现了没有,我们使用了很多以双下划线开头和结尾的属性和方法,比如 __init__ 等。

    64310

    Python学习笔记(七)·面向对象高级编程

    ' 由于'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() >>

    53220

    Python 魔法方法之__getattr__(self,name)

    前言 当实例对象调用一个不存在的属性时,系统通常会报错,那有啥办法避免这种现象么,或者说自定义报错信息,答案是肯定的,我们可以通过定义__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异常,属性查找失败!

    1.6K20

    魔法方法(2)

    例如,读取属性(具体来说,是实例中访问类中定义的属性)时,如果它关联的是一个实现了__get__的对象,将不会返回这个对象,而是调用方法__get__并将其结果返回。...__getattribute__(self, name):在属性被访问时自动调用(只适用于新式类)。 __getattr__(self, name):在属性被访问而对象没有这样的属性时自动调用。...仅当没有找到指定的属性时,才会调用方法__getattr__。这意味着如果指定的名称不是size,这个方法将引发AttributeError异常。...有些人可能之前只使用for循环迭代过序列和字典,但实际上也可迭代其他对象:实现了方法__iter__的对象。...---- 注意 更正规的定义是,实现了方法__iter__的对象是可迭代的,而实现了方法__next__的对象是迭代器。 ---- 首先,创建一个Fibs对象。

    72530

    Python面向对象编程-魔术方法-__call__和__getattr__方法

    在Adder类的实例化过程中,我们将数字5传递给了构造方法__init,从而初始化了Adder对象的属性n。...然后,我们创建了一个名为add5的Adder对象,并使用()运算符将数字3传递给了add5对象。...这时,Python会自动调用add5对象的__call__方法,将数字3作为参数传递给__call__方法,并返回n + x的结果,即8。...当我们使用点运算符访问一个对象的属性时,如果该属性不存在,Python会自动调用该对象的__getattr__方法,并将属性名称作为参数传递给__getattr__方法。...如果属性名称不为'x'或者'y',则会抛出AttributeError异常。因此,我们可以使用__getattr__方法为对象动态添加属性,从而实现灵活的对象属性访问行为。

    78482
    领券