6、第六 - 面向对象高级语法-类的特殊成员方法

 class类中,特殊成员的调用方法介绍。

类的特殊成员

 1、__doc__  表示类的描述信息

class Foo(object):
    """注析:描述类信息,很是神奇 """
    def fun(self):
        pass

print(Foo.__doc__) #调用,打印注析文档。
输出:
注析:描述类信息,很是神奇 

 2、__module__  与 __class__

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

__class__   表示当前操作的对象的类是什么

第一步:参考上个例子,并且命名为:Ok.py
class FOO(object):
    """注析:描述类信息,很是神奇 """
    def fun(self):
        pass

print(FOO.__doc__) #调用输出注析文档

第二步:写另外一个调用的模块,并且命名为:modAndclass.py

from Ok import FOO

obj = FOO()
print (obj.__module__) #输出OK,即输出模块
print (obj.__class__)   #输出OK.Foo,即输出类的名字

输出:

注析:描述类信息,很是神奇 
Ok
<class 'Ok.FOO'>

 3、__init__  类中的构造函数,通过类创建对象时,自动触发执行。

举例:

class Name(object):

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

    def talk(self):
        print("%s talking ......" % self.name)

w = Name("chen1203")
w.talk()
输出:
chen1203 talking ......

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

备注:此方法一般无须定义,开发使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

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

 备注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()。

举例:
class Name:

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

    def talk(self):
        print("%s talking ......" % self.name)

w = Name("chen1203")
w.talk() #正常的调用方式
w() #使用此方法调用就会报错。
输出如下:
chen1203 talking ......

Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/modAndclass.py", line 11, in <module>
    w()
TypeError: 'Name' object is not callable

 要想上面例子中,w() 可以正常的调用。要添加__call__函数,修改如下;

例1:使用w()直接调用
class Name:

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

    def talk(self):
        print("%s talking ......" % self.name)

    def __call__(self, *args, **kwargs):  
        print ("%s call me " % self.name)

w = Name("chen1203")
w.talk()
w()
输出:
chen1203 talking ......
chen1203 call me 

例2:使用w("qing") 传入参数

class Name:

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

    def talk(self):
        print("%s talking ......" % self.name)

    def __call__(self, *args, **kwargs):
        print (" call me ",args,kwargs)

w = Name("chen1203")
w.talk()
w('1','2','3','chen',mingzi="qing1203" )
输出:
chen1203 talking ......
call me  ('1', '2', '3', 'chen') {'mingzi': 'qing1203'}

备注:w()传入参数之后, 会按照元组、字典的方式打印出来。

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

举例:

class Name(object):

    country = "China"

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

    def talk(self):
        print("%s talking ......" % self.name)

    def __call__(self, *args, **kwargs):
        print ("call me ",args,kwargs)

#获取类的成员,即静态字段、函数构造方法的都有哪些。
print (Name.__dict__)
#输出:{'__dict__': <attribute '__dict__' of 'Name' objects>, '__doc__': None, '__call__': <function Name.__call__ at 0x10217aea0>, '__init__': <function Name.__init__ at 0x10217a9d8>, '__weakref__': <attribute '__weakref__' of 'Name' objects>, 'talk': <function Name.talk at 0x10217aa60>, '__module__': '__main__', 'country': 'China'}


#获取obj的成员
obj = Name("beijing",1203)
print (obj.__dict__)
#输出 :{'name': 'beijing', 'count': 1203}

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

举例:

class Name:

    country = "China"

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

    def talk(self):
        print("%s talking ......" % self.name)

    def __call__(self, *args, **kwargs):
        print ("call me ",args,kwargs)

    def __str__(self):
        print ("name is %s " % self.name)
        return "qing1203"

obj = Name("chen1203",1234)
print (obj) #默认会调用输出 __str__ 方法中的返回值
输出:
name is chen1203 
qing1203

 8、__getitem__、__setitem__、__delitem__  用于索引操作,如字典。以上分别表示获取、设置、删除数据

举例:

class Foo(object):

    def __init__(self):
        self.data = {}

    def __getitem__(self, key):
        print('__getitem__', key)

    def __setitem__(self, key, value):
        print('__setitem__', key, value)
        self.data[key] = value

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

obj = Foo()
obj["chen"] = "1203" #添加字典类目,默认调用setitem方法
obj["qing"] = "1204" #添加字典类目,默认调用setitem方法
print (obj.data) #把字典中的信息,也全部打印
del obj["qing"] #其实,没有真正意义上的删除。
print (obj.data) #把字典中的信息,也全部打印了
print (obj.data["qing"]) #调出为qing, 的value值
输出:
__setitem__ chen 1203
__setitem__ qing 1204
{'qing': '1204', 'chen': '1203'}
__delitem__ qing
{'qing': '1204', 'chen': '1203'}
1204

备注:python2.7版本里面,可以把实例变成列表;python3 版本里面就是没这个方法了

9、__new__ 、 __metaclass__  

class Foo(object):

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

f = Foo("alex")
print (type(f)) # 输出:<class '__main__.Foo'>     表示,f 对象由Foo类创建
print (type(Foo))# 输出:<type 'type'>              表示,Foo类对象由 type 类创建
输出:
<class '__main__.Foo'>
<class 'type'>

   上述代码中,f 是通过 Foo 类实例化的对象,其实,不仅 f 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

f 对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法创建。所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

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

1)、普通方法创建:

class Foo(object):

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

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

f = Foo("alex") #创建对象,实例化类

 2)、特殊方式(装B方式)

def func(self):
    print("hello world %s" % self.name)

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

F = type('Foo1',(object,),{'talk':func,'__init__':__init__})
#type第一个参数:类名,注:(object,) 括号里面的object必须要跟一个逗号
#type第二个参数:当前类的基
#type第三个参数:类的成员
ok = F("chen",1203)
ok.talk()
输出:
hello world chen

 注:类是由 type 类实例化产生。

下面,先介绍 __new__的使用方法: 就是用来创建实例的.在__init__之前创建方法。

举例:

class Foo(object):

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

        print("Foo __init__",self.name)

     def __new__(cls, *args, **kwargs):
        print("Foo __new__",cls, *args, **kwargs)
        return object.__new__(cls) #继承父类的__new__方法

obj = Foo("chen1203")
输出:
Foo __new__ <class '__main__.Foo'> chen1203
Foo __init__ chen1203

#执行顺序为:new --> init 。先执行的new,再把底参数上传到init的self中传参。
如果修改了下下面的对象调用后:
obj = Foo("chen1203",1234,"fasfa")
输出信息为:
Foo __new__ <class '__main__.Foo'> chen1203 1234 fasfa  #new的执行是成功的
Traceback (most recent call last):
File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/newAndmetathod.py", line 12, in <module>
obj = Foo("chen1203",1234,"fasfa")
TypeError: __init__() takes 2 positional arguments but 4 were given 

 

类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

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

举例1:  不添加  __metaclass__

举例1:
class MyType(type):
    def __init__(self, *args, **kwargs):
        print("Mytype __init__", *args, **kwargs)

    def __call__(self, *args, **kwargs):
        print("Mytype __call__", *args, **kwargs)
        obj = self.__new__(self)
        print("obj ", obj, *args, **kwargs)
        print(self)
        self.__init__(obj, *args, **kwargs)
        return obj

    def __new__(cls, *args, **kwargs):
        print("Mytype __new__", *args, **kwargs)
        return type.__new__(cls, *args, **kwargs)

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("chen1203")
print("f", f)
print("fname", f.name)
输出:
Foo __init__
f <__main__.Foo object at 0x102194438>
fname chen1203

注:不会调用到上到上面的 MyType. ...因为没有类的继承。

 举例2: 添加 __metaclass__ 由 MyType  类创建实例化

class MyType(type):

    def __init__(self, *args, **kwargs):
        print("Mytype __init__", *args, **kwargs)

    def __call__(self, *args, **kwargs):
        print("Mytype __call__", *args, **kwargs)
        obj = self.__new__(self)
        print("obj ", obj, *args, **kwargs)
        print(self)
        self.__init__(obj, *args, **kwargs)
        return obj

    def __new__(cls, *args, **kwargs):
        print("Mytype __new__", *args, **kwargs)
        return type.__new__(cls, *args, **kwargs)

class Foo(object, metaclass=MyType): #或者写到下面 像__metaclass__ = MyType
    #__metaclass__ = MyType
    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("chen1203")
print("f", f)
print("fname", f.name)

输出:
Mytype __new__ Foo (<class 'object'>,) {'__new__': <function Foo.__new__ at 0x101995048>, '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x10197af28>, '__module__': '__main__'}
Mytype __init__ Foo (<class 'object'>,) {'__new__': <function Foo.__new__ at 0x101995048>, '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x10197af28>, '__module__': '__main__'}
Mytype __call__ chen1203
Foo __new__ <class '__main__.Foo'>
obj  <__main__.Foo object at 0x101994470> chen1203
<class '__main__.Foo'>
Foo __init__
f <__main__.Foo object at 0x101994470>
fname chen1203

注意:打印的执行顺序 Mytype __new__ --> Mytype __init__ --> Mytype __call__ -->Foo __new__ --> Foo __init__ 

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

如图解析

 

posted on 2018-03-08 20:51  C.Q&CHEN  阅读(148)  评论(0)    收藏  举报

导航