Python 面向对象编程(进阶II)
类成员的修饰符
对于每一个类的成员而言都有两种形式:
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法。私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
私有成员和公有成员的访问限制不同:
静态字段
- 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
- 私有静态字段:仅类内部可以访问;
class C:
name_public = "pubic static"
def func(self):
print(C.name_public) # 类内部可以访问
class D(C):
def show(self):
print(C.name_public) # 派生类中可以访问
print(C.name_public) # 类访问
obj = C()
obj.func()
obj_son = D()
obj_son.show()
class C:
__name_private = "private static"
def func(self):
print(C.__name_private)
class D(C):
def show(self):
print(C.__name_private)
print(C.__name_private) # 类不可以访问
obj = C()
obj.func() # 类内部可以访问
obj_son = D()
obj_son.show() # 派生类不可以访问
普通字段
- 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
- 私有普通字段:仅类内部可以访问;
ps:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。
class C:
def __init__(self):
self.name_public = "public ordinary"
def func(self):
print(self.name_public) #类内部访问
class D(C):
def show(self):
print(self.name_public) #派生类中访问
obj = C()
print(obj.name_public) # 通过对象访问
obj.func()
obj_son = D()
obj_son.show()
#!/usr/bin/env python
class C:
def __init__(self):
self.__name_private = "private ordinary"
def func(self):
print(self.__name_private) #类内部可以访问
class D(C):
def show(self):
print(self.__name_private) #派生类中不可以访问
obj = C()
print(obj.__name_private) # 通过对象不可以访问
obj.func()
obj_son = D()
obj_son.show()
方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用
ps:非要访问私有属性的话,可以通过 对象._类__属性名
类的特殊成员
1. __doc__ 表示类的描述信息
2. __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class Foo: """ description """ def func(self): pass print(Foo.__doc__)
obj=Foo()
print(obj.__module__)
print(obj.__class__)
执行结果:
description
__main__
<class '__main__.Foo'>
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4. __del__ 析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
5. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
6. __dict__ 获取类或对象中的所有成员,以字典的形式返回 {成员名:值,}
7. __str__ 如果一个类中定义了__str__方法,那么在打印对象 时,默认输出该方法的返回值。
class Foo: def __str__(self): return '__str__' obj = Foo() print(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() obj['k1'] # 自动触发执行 __getitem__ obj['k2'] = 'v2' # 自动触发执行 __setitem__ del obj['k1'] # 自动触发执行 __delitem__
9. __iter__ 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
class Foo(object): def __init__(self, sq): self.sq = sq def __iter__(self): return iter(self.sq) obj = Foo([11,22,33,44]) for i in obj: print(i)
等同于obj
=
iter
([
11
,
22
,
33
,
44
])
for
i
in
obj:
print(i)
类由 type 类实例化产生
class Foo(object): def __init__(self): pass obj = Foo() print(type(obj)) print(type(Foo))
执行结果:
<class '__main__.Foo'>
<class 'type'>
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
obj对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:类 是由 type 类实例化产生
反射
反射是通过字符串的形式操作对象相关的成员
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
import sys
class WebServer(object):
def __init__(self,host,port):
self.host=host
self.port=port
def start(self):
print('Server is starting')
def stop(self):
print('Server is stopping')
def restart(self):
self.stop()
self.start()
def test(ins,name):
print('runing...',name,ins.host)
if __name__ == '__main__':
server=WebServer('localhost',333)
if hasattr(server,sys.argv[1]):
func=getattr(server,sys.argv[1])
func()
setattr(server,'run',test) ## server.run=test
server.run(server,'Bob')
delattr(server,'host')
server.restart()
delattr(WebServer,'start')
server.restart()
执行结果:
Server is starting
runing... Bob localhost
Server is stopping
Server is starting
Server is stopping
AttributeError: 'WebServer' object has no attribute 'start'