魔法方法和属性

在python中,有的名称会在前面和后面都加上两个下划线,这种写法很特别,同时表示名字有特殊含义,所以绝不要在自己的程序中使用这种名字。

在python中,这种名字组成的集合所包含的方法称为魔法(或特殊)方法。

如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切的说是根据名字)被python调用。

很久以前(Python2.2中),对象的工作方式就有了很大的变化。这种改变产生了一些影响,但对于刚开始使用python的人来说,大多数都不重要。

值得注意的是,尽管可能是用的是新版的python,但有一些特性不会在老式类上起作用。

为了确保类是新型的,应该把赋值语句__metaclass__=type放在你的模块的最开始。或者(直接或者间接)子类化内建类object。

 

1.构造方法

首先要讨论的第一个魔法方法是构造方法。构造方法是一个很奇特的名字,它代表着类似于以前例子中使用过的那种名为init的初始化方法。

但构造方法和其他普通方法不同的地方在于,当一个对象被创建后,会立即调用构造方法。

在python中创建一个构造方法很容易。只要把init方法的名字从简单的init修改为魔法版本的__init__即可:

>>> class Foobar:
...     def __init__(self):
...             self.somevar = 42
...
>>>
>>> f = Foobar()
>>> f.somevar
42

如果要给构造方法传几个参数的话,会发生什么情况了?

>>> class Foobar:
...     def __init__(self,value=42):   #参数可选
...         self.somevar = value   #有点类似于函数的传参
...

参数可选,传个参数试试

>>> f = Foobar(‘This is a constructor argument‘)
>>> f.somevar
‘This is a constructor argument‘

在所有的魔法方法中,__init__是使用最多的一个。

2.重写一般方法和特殊的构造方法

在继承的知识中,每个类都有可能拥有一个或者多个超类,它们从超类那里继承行为方式。

如果一个方法在B类的一个实力被调用(或一个属性被访问),但在B类中没有找到方法,那么就会取它的超类里面找。

>>> class A:
...     def hello(self):
...         print("Hello,I‘m A.")
...
>>> class B(A):
...     pass
...
>>> a = A()
>>> b =B()
>>> a.hello()
Hello,I‘m A.
>>> b.hello()   #A继承了一个叫hello的方法,被B继承。
Hello,I‘m A.

因为B类没有自己的构造方法,所以当hello被调用时,原始的信息就被打印出来。

在子类中增加功能的最基本的方法是增加方法,但是也可以重写一些超类的方法来定义继承的行为。

>>> class B(A):
...     def hello(self):
...         print("Hello,I")
...
>>> b.hello()
Hello,I

重写是继承机制中的一个重要内容,对于构造方法尤为重要。

构造方法用来初始化新创建对象的状态,大多数字类不仅要拥有自己的初始化代码,还要拥有超类的初始化代码。

虽然重写的机制对于所有方法都是一样的,但是当处理构造方法比重写普通方法时,更可能遇到特别的问题:如果一个类的构造方法被重写,那么就需要调用超类(你所继承的类)的构造方法,否则可能不会被正确的初始化。

考虑下面的Bird类:

class Bird:
    def __init__(self):
        self.hungry = True
    def ear(self):
        if self.hungry :
            print(‘Aaaah...‘)
            self.hungry = False
        else:
            print(‘No,thanks‘)

定义了鸟最基本的能力——吃,

Aaaah...
No,thanks

吃过之后,它就不再饥饿了,加入子类SongBird。

class SongBird(Bird):
    def __init__(self):
        self.sound = ‘Squawk‘
    def sing(self):
        print(self.sound)

一样可以生成对象,并且调用其中的方法。

sb = SongBird()
sb.sing()

结果:
Squawk

SongBird是Bird的子类,能否继承其中的方法了?试一下

sb.ear()
结果:
Traceback (most recent call last):
  File "I:/untitled/cx/11月/函数.py", line 23, in <module>
    sb.ear()
  File "I:/untitled/cx/11月/函数.py", line 5, in ear
    if self.hungry :
AttributeError: ‘SongBird‘ object has no attribute ‘hungry‘

Why?Why?...

异常很清楚的说明了错误:SongBird没有hungry的特性。

原因是这样的:在SongBird中,构造方法被重写,但新的构造方法没有任何关于hungry特性的代码。

为了达到预期的效果,SongBird的构造方法必须被重写,有两种方法能够达到这一目的:调用未绑定的构造方法,或者使用super函数。

3.调用未绑定的超类的构造方法

调用超类的构造方法其实很简单,只需要在刚才的例子上小小的改动。

class SongBird(Bird):
    def __init__(self):
        Bird.__init__(self)  #就是如此简单
        self.sound = ‘Squawk‘
    def sing(self):
        print(self.sound)

结果:

sb.ear()

Aaaah...

为什么会有这样的结果了?在调用一个实例方法的时候,该方法的self参数会被自动绑定到实例上(这称为绑定方法)。

如果直接调用类的方法(比如:Bird.__init__),那么就没有实例会被绑定。

这样就可以自由的提供需要的self参数了,这样的方法称为未绑定的方法。

4.使用super函数

如果你不想坚守旧版本的Python阵营,也可以使用super函数,但是它只能在新式类中使用。当前的类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类的方法,而不是当前类的方法。

class SongBird(Bird):
    def __init__(self):
        super(SongBird,self).__init__()
        self.sound = ‘Squawk‘
    def sing(self):
        print(self.sound)

sb = SongBird()
sb.ear()
sb.ear(

结果:
Aaaah...
No,thanks
时间: 2024-10-08 17:30:41

魔法方法和属性的相关文章

《Python基础教程(第二版)》学习笔记 -&gt; 第九章 魔法方法、属性和迭代器

准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here 在这两个类中,NewStyle是新式的类,OldStyle是旧式的类,如果文件以__metaclass__ = type 开始,那么两个类都是新式类. 构造方法 构造方法,当一个对象被创建后,会立即调用构造方法.Python中创建一个构造方法,只要把init方法的名字从简单的init修改成__init__

python基础教程_学习笔记11:魔法方法、属性和迭代器

魔法方法.属性和迭代器 在python中,有的名称会在前面和后面各加上两个下划线,这种写法很特别.它表示名字有特殊含义,所以绝不要在自己的程序中使用这种名字.在python中,由这些名字组成的集合所包含的方法叫做魔法(或称特殊)方法.如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下被python调用,而几乎没有直接调用它们的必要. 准备工作 为了确保类是新型的,应该把赋值语句__metaclass__=type放在你的模块的最开始,或者(直接或间接)子类化内建类(实际上是类型)ob

python 魔法方法,属性,迭代

9.2 构造方法 python 中也属于自己的构造函数和析构函数, class fibs: def __init__(self): self.a = 0 self.b = 1 def next(self): self.a,self.b = self.b,self.a+self.b return self.a def __iter__(self): return self fib = fibs() for i in fib: if i>1000: print i break 其中的__init__

Python基础教程(第九章 魔法方法、属性和迭代器)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5437223.html______ Created on Marlowes 在Python中,有的名称会在前面和后面都加上两个下划线,这种写法很特别.前面几章中已经出现过一些这样的名称(如__future__),这种拼写表示名字有特殊含义,所以绝不要在自己的程序中使用这样的名字.在Python中,由这些名字组成的集合所包含的方法称

&lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第09章 | 魔法方法、属性和迭代器

这一章,有点抽象,看着有点蛋疼! 双下划线__future__或单下划线有特殊含义,在Python中,这些名字的集合称为魔法方法:最重要的是__init__和一些处理访问对象的方法,这些方法允许你创建自己的序列或者是映射. ------ 准备工作: 将__metaclass__=type放在模块的最开始位置,以确保类时最新式的.考虑下面两个类 class NewStyle(object): more_code_here class OldStyle: more_code_here 如果文件以__

魔法方法:属性访问

__getattr__(self,name) 当用户试图访问name,而name属性不存在时就会调用getattr __getattribute__(self,name) 当用户试图访问name时就会调用getattribute __setattr__(self,name,value)当name被设置为value的时候就会调用setattr __delattr__(self,name)当name属性被删除时就会调用delattr 只有重写以上四个魔法方法,就可以改变属性访问

Python3 魔法方法:属性访问

1.与属性访问有关的魔法方法 __getattr__(self,name) 定义当用户试图获取某一不存在的属性时的行为 __getattribute__(self,name) 定义当该类属性被访问时的行为 __setattr__(self,name,value) 定义一个属性被设置时的行为 __delattr__(self,name) 定义一个属性被删除时的行为 注意: def __setattr__(self, name, value): self.name = value + 1 #此代码试

《Python基础教程》 读书笔记 第九章 魔法方法、属性和迭代器(上)

构造方法 在Python中创建一个构造方法很容易.只要把init方法的名字从简单的init修改为魔法版本__init__即可: >>> class FooBar: ...     def __init__(self): ...         self.somevar=42 ... >>> f=FooBar() >>> f.somevar 42 给构造方法传几个参数 >>> class FooBar: ...     def __in

python学习(九) 魔法方法、属性和迭代器

9.1 准备工作 python 3.0的所有类都会隐式地成为object的子类. 9.2 构造方法 在python中创建一个构造方法:只要把init方法的名字修改为魔法版本__init__即可. >>> class FooBar: def __init__(self): self.somevar = 42 >>> f = FooBar() >>> f.somevar 42 __def__ :是析构方法,但是调用时机不确定,所以不建议使用. 9.2.1