类的特殊成员方法

Posted 当幸福来敲门

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类的特殊成员方法相关的知识,希望对你有一定的参考价值。

类的特殊成员方法

1、__doc__  表示类的描述信息

class Dog(object):
    \'\'\'这个是描述狗的一个类\'\'\'
    def __init__(self,name):
        self.name = name
        self.__weight = 100

    def sayhi(self):
        print(\'my wigth is \', self.__weight,)

d = Dog(\'二哈\')
print(d.__doc__)  #这个是描述狗的一个类
print(Dog.__doc__) #这个是描述狗的一个类

 2、__module__ 和 __class__

__module__ 表示当前操作的对象在哪个模块

__class__ 表示当前操作的对象是哪个类

3、__init__ 构造方法,类在实例化创建对象时,自动触发的方法

4、__del__ 析构方法  当对象在内存被释放时,自动触发执行。

5、__call__ 对象后面加括号,触发执行

class Dog(object):
    \'\'\'这个是描述狗的一个类\'\'\'
    def __init__(self,name):
        self.name = name
        self.__weight = 100

    def sayhi(self):
        print(\'my wigth is \', self.__weight,)
    def __call__(self, *args, **kwargs):
        print(\'runing call\',args,kwargs)
d = Dog(\'二哈\')
Dog(\'二哈\')() #runing call () {}
d(1,2,3,4,5,name=888) #runing call (1, 2, 3, 4, 5) {\'name\': 888}

 6、__dict__ 查看类或者对象中的所有成员

class Dog(object):
    \'\'\'这个是描述狗的一个类\'\'\'
    def __init__(self,name):
        self.name = name
        self.__weight = 100

    def sayhi(self):
        print(\'my wigth is \', self.__weight,)
    def __call__(self, *args, **kwargs):
        print(\'runing call\',args,kwargs)
d = Dog(\'二哈\')
print(Dog.__dict__) 
#{\'__dict__\': <attribute \'__dict__\' of \'Dog\' objects>, \'__doc__\': \'这个是描述狗的一个类\', \'__init__\': <function Dog.__init__ at 0x00000000010501E0>, 
#\'__call__\': <function Dog.__call__ at 0x00000000010502F0>, \'sayhi\': <function Dog.sayhi at 0x0000000001050268>, \'__module__\': \'__main__\',
#\'__weakref__\': <attribute \'__weakref__\' of \'Dog\' objects>} #打印类里面的所有属性,不包括实例。 print(d.__dict__) #{\'_Dog__weight\': 100, \'name\': \'二哈\'} 打印所有实例的属性,不包括类。

 7、__str__ 如果一个类定义了__str__方法 ,那么在打印对象时。默认输出该方法的返回值

class Dog(object):
    \'\'\'这个是描述狗的一个类\'\'\'
    def __init__(self,name):
        self.name = name
        self.__weight = 100

    def sayhi(self):
        print(\'my wigth is \', self.__weight,)
    def __call__(self, *args, **kwargs):
        print(\'runing call\',args,kwargs)
    def __str__(self):
        return "obj:%s" % self.name
d = Dog(\'二哈\')
d1 = Dog(\'秋田\')
print(d) # obj:二哈
print(d1) # obj:秋田

 8、__getitem__、__setitem__、__delitem__

用于索引操作,比如字典、以上表示获取、设置、删除数据。

class Foo(object):
    def __getitem__(self, key):
        print(\'__getitem__\',key)

    def __setitem__(self, key, value):
        print(\'__setitem__\',key,value)

    def __delitem__(self, key):
        print(\'__delitem__\',key)

obj = Foo()
result = obj[\'k1\']   # __getitem__ k1
obj[\'k2\'] = \'alex\'  # __setitem__ k2 alex
del obj[\'k1\']   #  __delitem__ k1

 9、__new__ \\ __metaclass__

一切事物皆对象。

class Foo(object):
    def __init__(self,name):
        self.name = name

f = Foo(\'alex\') 
print(type(f)) #<class \'__main__.Foo\'>
print(type(Foo)) #<class \'type\'>

 可以看到f是实例化Foo后的一个对象,不仅f是一个对象,Foo类本身也是一个对象。

f对象是Foo的一个实例,Foo类是type类的一个实例。说明Foo类是通过type类的构造方法创建。

那么,创建类就可以有两种方式:

1、普通方式

class Foo(object):
    def __init__(self,name):
        self.name = name

f = Foo(\'alex\')

2、特殊方式

def func(self):
    print(\'hello world\')

Foo = type(\'Foo\',(),{\'func\':func}) #Foo表示要实例化之后的类,()表示要继承的类,func表示类里面的方法

print(type(Foo))
f= Foo() #<class \'type\'>
f.func() #hello world

 

既然可以通过这种方式创建类,并且可以添加类的方法,也可以把__init__这种方法装载进去。

def func(self):
    print(\'hello world\')

def __init__(self,name,age):
    self.name = name
    self.age = age

Foo = type(\'Foo\',(),{\'func\':func,\'__init__\':__init__}) #Foo表示要实例化之后的类,()表示要继承的类,func表示类里面的方法
 
f= Foo() #TypeError: __init__() missing 2 required positional arguments: \'name\' and \'age\'

 这里提示实例化的时候__init__里面要传入两个参数。

def func(self):
    print(\'hello world\')

def __init__(self,name,age):
    self.name = name
    self.age = age

Foo = type(\'Foo\',(),{\'func\':func,\'__init__\':__init__}) #Foo表示要实例化之后的类,()表示要继承的类,func表示类里面的方法

f= Foo(\'alex\',\'age\')
print(f.name,f.age) #alex age

 那么,类默认是通过type类实例化产生,type类如何创建类?类又是如何创建对象的?

其实类中有一个属性 __metaclass__,其用来表示该类由谁来实例化创建的。所以可以为__metaclass__设置一个type类的派生类,从而查看类创建的过程。

 

 1 class MyType(type):
 2     def __init__(self,*args,**kwargs):
 3 
 4         print("Mytype __init__",*args,**kwargs)
 5 
 6     def __call__(self, *args, **kwargs):
 7         print("Mytype __call__", *args, **kwargs)
 8         obj = self.__new__(self)
 9         print("obj ",obj,*args, **kwargs)
10         print(self)
11         self.__init__(obj,*args, **kwargs)
12         return obj
13 
14     def __new__(cls, *args, **kwargs):
15         print("Mytype __new__",*args,**kwargs)
16         return type.__new__(cls, *args, **kwargs)
17 
18 print(\'here...\')
19 class Foo(object,metaclass=MyType):
20 
21 
22     def __init__(self,name):
23         self.name = name
24 
25         print("Foo __init__")
26 
27     def __new__(cls, *args, **kwargs):
28         print("Foo __new__",cls, *args, **kwargs)
29         return object.__new__(cls)
30 
31 f = Foo("Alex")
32 print("f",f)
33 print("fname",f.name)
34 
35 自定义元类
View Code

__new__()方法

class Foo(object):

    def __init__(self,name):
        self.name = name

        print("Foo __init__")

    def __new__(cls, *args, **kwargs):
        print("Foo __new__",cls, *args, **kwargs)
        return object.__new__(cls)

f = Foo("Alex") 
#=========执行结果============
Foo __new__ <class \'__main__.Foo\'> Alex
Foo __init__

 实例化Foo类的时候会执行__init__,也会执行__new__。并且__new__会在__init__之前执行。

有一点不明白的是__new__()方法里面的return object.__new__(cls) 做什么用的?

尝试去掉这个return:

class Foo(object):

    def __init__(self,name):
        self.name = name

        print("Foo __init__")

    def __new__(cls, *args, **kwargs):
        print("Foo __new__",cls, *args, **kwargs)


f = Foo("Alex")
#=============执行结果============
Foo __new__ <class \'__main__.Foo\'> Alex

 可以看到只执行了__new__()方法,并没有执行__init__这个方法。说明这个实例并没有真正被创建。

print(f.name) #AttributeError: \'NoneType\' object has no attribute \'name\'

说明__new__()用来创建实例的,object.__new__用父类的方法创建实例,那么传过去的cls做什么的?

cls 相当于self,也就是Foo,因为Foo也是一个对象,你要继承父类的东西就要把自己传过去。

print(object.__new__(cls)) #<__main__.Foo object at 0x0000000000A52320> #Foo内存对象

 

__metaclass__

 

 

 1 class MyType(type):
 2     def __init__(self,*args,**kwargs):
 3 
 4         print("Mytype __init__",*args,**kwargs)
 5         super(MyType, self).__init__( *args,**kwargs)
 6 
 7     def __call__(self, *args, **kwargs):
 8         print("Mytype __call__", *args, **kwargs)
 9         #obj = self.__new__(self)
10         #self.__init__(obj,*args, **kwargs)
11 
12 class Foo(object):
13     __metaclass__ = MyType
14     def __init__(self,name):
15         self.name = name
16 
17         print("Foo __init__")
18 
19     def __new__(cls, *args, **kwargs):
20         print("Foo __new__",cls, *args, **kwargs)
21         return object.__new__(cls)
22 
23 f = Foo("Alex")
View Code

 类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

 metaclass 详解文章:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 得票最高那个答案写的非常好

 

以上是关于类的特殊成员方法的主要内容,如果未能解决你的问题,请参考以下文章

面向对象day08:类的特殊成员-类的起源与metaclass

Python学习:17.Python面向对象(属性(特性),成员修饰符,类的特殊成员)

Python面向对象--类的特殊成员方法

Python 类的特殊成员方法

###类的特殊成员方法

类的成员,类的特殊方法