一.python面向对象之__slots__
1.为对象和实例添加属性/方法:
python是一种动态编程语言,可以动态为类和实例添加属性.
定义类:
class Dog:
pass
定义一个方法:
def get_name(self):
return self.__name
给类动态添加属性和方法:
Dog.__name = 'tiger'
Dog.get_name = get_name
#调用
dog = Dog()
print(dog.get_name())
输出:
tiger
给实例添加属性和方法:
from types import MethodType
dog = Dog()
dog.__name = 'tiger'
dog.get_name = MethodType(get_name, dog)
print(dog.get_name())
输出:
tiger
2.如果要限制添加的属性怎么办?使用__slots__
示例:
class Dog:
__slots__ = ('get_name', 'name')
def get_name(self):
return self.name
仅允许为Dog类和实例动态添加get_name和name属性,添加其他属性引发AttributeError错误
dog = Dog()
dog.name = 'tiger'
dog.age = 10
dog.get_name = MethodType(get_name, dog)
print(dog.get_name())
输出:
AttributeError: 'Dog' object has no attribute 'name'
注意:__slots__不会对继承不起作用,仅对当前类和示例起作用.
二.python面向对象之@property
Python内置的@property装饰器就是负责把一个方法变成属性调用
示例:
class Dog:
def __init__(self):
self.__age = 0
@property
def age(self):
return self.__age
@age.setter
def age(self, val):
self.__age = val
dog = Dog()
dog.age = 10
print(dog.age)
三.定制类
python为类提供了一些内置属性,可以方便的对类进行定制
1.__str__和__repr__:
__str__:是打印示例输出的内容
__repr__:是在交互命令下输出的实例内容
示例:
class Dog:
def __str__(self):
return 'class Dog'
# 直接将__str__属性复制给__repr__
__repr__ = __str__
dog = Dog()
print(dog)
2.__iter__和__next__:
让类可以被迭代
示例代码:
class Dog:
def __init__(self):
self.__max = 10
self.__index = 0
def __iter__(self):
return self
def __next__(self):
if self.__index > 10:
raise StopIteration()
tmp = self.__index
self.__index += 1
return tmp
dogs = Dog()
for dog in dogs:
print(dog)
输出:
0
1
2
3
4
5
6
7
8
9
10
3.__getitem__:
让类可以像list一样取下标和切片
取下标示例代码:
class Dog:
def __init__(self):
self.__list = range(10)
def __getitem__(self, index):
if index >= len(self.__list):
raise IndexError()
return self.__list[index]
dogs = Dog()
print(dogs[1])
输出:
1
既可以取下标又可以切片示例代码:
class Dog:
def __init__(self):
self.__list = range(10)
def __getitem__(self, index):
if isinstance(index, int):
if index >= len(self.__list):
raise IndexError()
return self.__list[index]
if isinstance(index, slice):
return list(self.__list)[index.start:index.stop]
dogs = Dog()
print(dogs[1:5])
输出:
[1, 2, 3, 4]
4.__getattr__和__setattr__:
__getattr__:但读取属性时,如果不存在则调用
__setattr__:但设置属性时,如果不存在则调用
示例代码:
class Dog(dict):
def __init__(self):
self.__name = 'dog'
def __getattr__(self, item):
return self[item]
def __setattr__(self, key, value):
self[key] = value
dog = Dog()
dog.age = 10
dog.sex = 1
print(dog.age, dog.sex)
REST API路径示例:
class Chain:
def __init__(self, path=''):
self.__path = path
def __getattr__(self, item):
return Chain('%s/%s' % (self.__path, item))
def __str__(self):
return self.__path
path = Chain().v1.api.status
print(path)
输出:
/v1/api/status
5.__call__
将实例作为函数调用
callable可以判断对象是否可以作为函数调用
示例代码:
class Dog:
def __call__(self, name):
print('dog是一条狗,from-%s' % name)
dog = Dog()
if callable(dog):
dog('dahuang')
else:
print('not call')