python中常用魔术方法

__new__(cls, *args, **kwargs) 
        创建对象时调用,返回当前对象的一个实例;注意:这里的第一个参数是cls即class本身

__init__(self, *args, **kwargs)
         创建完对象后调用,对当前对象的实例的一些初始化,无返回值,即在调用__new__之后,根据返回的实例初始化;注意,这里的第一个参数是self即对象本身【注意和new的区别】
          写在类里面的方法第一个参数self不要漏写,这一点对所有方法同样

__call__(self,  *args, **kwargs)
         如果类实现了这个方法,相当于把这个类型的对象当作函数来使用,相当于 重载了括号运算符

如下一个简单的例子,来验证这三个函数的执行顺序:


class O(object):
    def __init__(self, *args, **kwargs):
        print "init"
        super(O, self).__init__(*args, **kwargs)
    def __new__(cls, *args, **kwargs):
        print "new", cls
        return super(O, cls).__new__(cls, *args, **kwargs)
    def __call__(self,  *args, **kwargs):
        print "call"
       
    oo = O()
    print "________"
    oo()  

执行结果如下:
由此可知,顺序为先执行了new方法创建了对象,而后执行了init方法初始化了对象的一些参数
根据上边三个函数的定义,call方法,就是把对象当做函数来是用来,比如oo(),就是执行了一个函数。

new
init
________
call

做个不一定对的类比:对应到ObjC中
          __new__相当于alloc
          __init__跟init一样
          __call__方法为独有的功能,就是对象变函数的利器

由此理解可推到出,在python的Singleton(单例)的模式,我们只需要写好__new__方法即可,因为__new__方法才是完成创建工作

class Singleton(object):
    """ 重载new方法"""
    def __new__(cls, *args, **kwargs):
        if not "_instance" in vars(cls):
            cls._instance = super(Singleton1, cls).__new__(cls, *args, **kwargs)
        return cls._instance


__del__()
   相当于析构函数dealloc(),在对象要被销毁前执行
 

__repr__()
  
自定义对象的输出模式

>>> class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __del__(self):
        print("I am dying...")
    def __repr__(self):
        return "Name: "+self.name+" Age:"+str(self.age)
>>> p = Person()
>>> p
Name: Xiaoming Age: 18
>>> print(p)
Name: xiaoming Age: 18

__repr__()有一个远房表亲__str__(),通常我们选择实现前者就够了,因为如果一个对象没有实现__str__()函数而Python又需要调用它的时候,解释器会用__repr__()作为代替 

__iter__()__next__()通常是成对出现的,用来创建用户自定义的迭代器

>>> class Fib(object):

        def __init__(self, limit):
            self.a = 0
            self.b = 1
            self.limit = limit

        def __iter__(self):
            return self    #迭代器自身也是一个支持迭代操作的可迭代对象,故每次迭代操作后返回自身

        def __next__(self):
            self.a, self.b = self.b, self.a+self.b
            if self.a > self.limit:    #记住,Pythonic的代码if语句是不加括号的
                raise StopIteration
            return self.a

>>> m = Fib(60)    #这里传入的limit参数不是执行的迭代次数而是元素大小的上限

>>> for i in m:
    print(m, end=" ")
1 1 2 3 5 8 13 21 34 55

__add__(),__sub__()__mul__()__mod__()
相当于实现了运算符重载,特别是要对用户自定义的类型定义一些操作集合时这些魔术方法十分常用

class Vector(object):

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vector(%r %r)' %(self.x, self.y)

    def __abs__(self):
        return hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))

    def __add__(self, other):
        x = self.x + other.x
        y = self.x + other.y
        return Vector(x,y)

    def __mul__(self, scalar):
        return Vector(self.x*scalar, self, self.y*scalar)

__str__()
这个函数也是python中比较常见的函数,其主要用来返回一个对象的描述信息,比如一个类有name,age,address等属性,那么就可以通过定义__str__()函数来返回这个类的描述信息。用法就是直接使用这个类的对象即可,一般用于打印输出等。

class Test():
    def __init__(self,name,age,addr):
        self.name = name
        self.age = age
        self.address = addr
    
    def __str__(self):
        print("我可以输出对象的描述信息")
        return '我的名字是:%s,我的年龄是:%s,我的地址:%s' % (self.name,self,age,self.address)
 
#调用
t = Test('alvin',28,'hangzhoushi')
print(t)
 
#输出结果:
"我可以输出对象的描述信息"
"我的名字是:alvin,我的年龄是:28,我的地址:hangzhoushi"

__str__()这个函数,怎么看都有点像是MacOS下的description函数,会自动调用的


__all__
它是一个列表类型的属性,不是定义在类的内部,而是定义在模块中的,主要是解决导入模块时的权限问题
导入一个模块有3种方式

import xxx
#将整个xxx模块导入,然后用模块名xxx.xx去使用模块中的对象

from xxx import *
#将模块xxx中所有的对象全部导入,然后直接使用,这样的缺点就是一旦后面导入的模块跟前面导入的模块中有重名的对象,那么前面导入的将会被覆盖掉

from xxx import x,xx
#只导入模块xxx中的x和xx两个对象,然后直接使用

模块开发中问题的提出:
      有时候我们定义好了一个模块,有的方法或属性只想在本模块内部使用不想让外部导入,这个时候该怎么办呢?
解决方法:
      只需要在模块中定义一个名为__all__的列表,然后把要开放的对象即可以被外部导入使用的对象,把对象名以字符串的形式添加到该列表中即可,这样外部就只能导入和使用在列表中定义过的对象,其它的是不能导入和使用的

#test.py模块
__all__ = ["test1","name"]
 
def test1():
    print("我是test1函数")
 
name = '我们是模块名'
 
def test2():
    print("我是test2函数,是内部函数不想让外部使用")

定义__all__后,通过import test或者是通过from import *导入的模块都不能访问test2()函数

python2.7 Data model
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

auspark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值