一.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')