Python 类与对象编程详解五(特殊成员)

上一篇:Python 类与对象编程详解四(封装、继承、多态)

类的特殊成员
doc

表示类的描述信息
实例:

class Foo:
    """描述类的信息"""
    def func(self):
        pass
print(Foo.__doc__)
foo = Foo
print(foo.__doc__)

运行结果:

描述类的信息
描述类的信息
module 和_class_

module 表示当前操作的对象在哪个模块
class 表示当前操作的对象的类是什么

实例:

from lib.aa import C
obj = C()

print obj.module  # 输出 lib.aa,即:输出模块

print obj.class      # 输出 lib.aa.C,即:输出类
init

构造方法、通过类创建对象时,自动触发执行。
实例:

class Role(object):    
#初始化函数,在生成一个角色时要    初始化的一些属性就填写在这里    
    def __init__(self,name,role):
        加粗样式self.name = name
        self.role = role
del

析构函数,当对象在内存中被释放时,自动触发执行

class Role(object):    
#初始化函数,在生成一个角色时要    初始化的一些属性就填写在这里    
    def __init__(self,name,role):
        self.name = name
        self.role = role
    def __del__(self):
        print("在摧毁对象前执行的操作")
a = Role("a","b")
print(a)
del a 
print(a)

运行结果:

<__main__.Role object at 0x000001A9431F1390>
在摧毁对象前执行的操作
NameError: name 'a' is not defined
call

类名后面加括号表示创建一个对象,如果在对象后加括号,就需要使用call方法了,如果不定义这个方法,在执行对象()的时候就会报错。

class A:
    def __call__(self, *args, **kwargs):
        print("call")
a = A()
a()
------------
call

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

a = A()()
dict

类或对象中所有成员
我们知道:类的实例属性属于对象,类中的类属性和方法等属于类
在这里插入图片描述
实例:

class Province:
    country = 'China'
    def __init__(self, name, count):
        self.name = name
        self.count = count


    def func(self, *args, **kwargs):
        print(func)


# 获取类的成员,即:静态字段、方法...
print (Province.__dict__)

# 获取 对象obj1 的成员
obj1 = Province('HeBei', 10000)
print (obj1.__dict__)
# 输出:{'count': 10000, 'name': 'HeBei'}

运行结果:

{'__module__': '__main__', 'country': 'China', '__init__': <function Province.__init__ at 0x0000021C7B32B7B8>, 'func': <function Province.func at 0x0000021C7B32BAE8>, '__dict__': <attribute '__dict__' of 'Province' objects>, '__weakref__': <attribute '__weakref__' of 'Province' objects>, '__doc__': None}
{'name': 'HeBei', 'count': 10000}
str

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

class Foo:
    def__str__(self):
        return'hello world'
 
obj = Foo()
print obj
# 输出:hello world
getitemsetitemdelitem

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

#!/usr/bin/env python
# -*- coding:utf-8 -*-

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__
obj['k2'] = 'wupeiqi'  # 自动触发执行 __setitem__
del obj['k1']  # 自动触发执行 __delitem__

运行结果:

__getitem__ k1
__setitem__ k2 wupeiqi
__delitem__ k1

在Python2.x中使用getslice setslice delslice来实现切片的操作,但是Python3.x中被遗弃,所有切片的功能都集中在了getitem setitem delitem中
实例:

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

    def __str__(self):
        return self.name

    def __getitem__(self, item):
        print("起点索引", item.start)
        print("终点索引", item.stop)
        print("步长", item.step)
        return "haha"

    def __setitem__(self, key, value):
        print("起点索引", key.start)
        print("终点索引", key.stop)
        print("步长", key.step)
        print("新值为", value)

    def __delitem__(self, key):
        print("起点索引", key.start)
        print("终点索引", key.stop)
        print("步长", key.step)

b = B("ps", 26)
print("切片取值")
ret = b[1:5:2]

print("切片赋值")
b[1:5:2] = "hehe"

print("切片删除")
print(ret)
del b[1:5:2]

------------
切片取值
起点索引 1
终点索引 5
步长 2
切片赋值
起点索引 1
终点索引 5
步长 2
新值为 hehe
切片删除
haha
起点索引 1
终点索引 5
步长 2
add

当执行一个对象 + 一个对象的时候,就会自动去执行这个方法

注意,执行的是第一个对象的add方法

class A:
    def __init__(self, num):
        self.num = num

    def __add__(self, other):
        return self.num + other.num

class B:
    def __init__(self, num):
        self.num = num        
a = A(5)
b = B(9)
c = a + b
print(c)
iter

一个自定义类实例化的对象,默认是不可迭代的,在类中使用iter方法后,对象就变成了可迭代对象。当对象被迭代时,会自动调用iter方法
实例1:

    pass

a = A()
for i in a:
    print(i)
    
------------
Traceback (most recent call last):
  File "/Users/lvrui/PycharmProjects/untitled/8/c8.py", line 5, in <module>
    for i in a:
TypeError: 'A' object is not iterablethon

实例2:

class A:
    def __iter__(self):
        return iter([1, 2])  # return了一个可迭代对象

a = A()
for i in a:
    print(i)
    
------------
1
2

实例3:

class A:
    def __iter__(self):  # 返回了一个生成器
        yield 1
        yield 2
        yield

a = A()
for i in a:
    print(i)
    
------------
1
2
None

2
先去a对象中找到iter方法执行,并拿到返回值进行迭代

new metaclass
class A(object):
 
    def __init__(self):
        pass     

a = A()   # a是通过A类实例化的对象

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

如果按照一切事物都是对象的理论:a对象是通过执行A类的构造方法创建,那么A类对象应该也是通过执行某个类的构造方法创建。

print type(a) # 输出:<class '__main__.A'>     表示,a对象由A类创建
print type(A) # 输出:<type 'type'>              表示,A类对象由type类创建

所以,a对象是A类的一个实例,A类对象是type类的一个实例,即:A类对象是通过type类的构造方法创建

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

class A(object):
 
    def func(self):
        print("ps")

特殊方式 (type类的构造函数)

def func(self):
    print("ps")
 
A = type('A',(object,), {'func': func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员

–> 类是由type类实例化产生

那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

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

在这里插入图片描述
由于篇幅过大,后面我会讲解自定义类metaclass和__new__的关系
下一篇:Python 类与对象编程详解五(抽象类,接口类)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值