对象
# object 为需要继承的父类
class Student(object):
# 所有类中的方法,第一个参数都是 self,但是实际调用的时候不需要传入
def __init__(self, name, age):
# __开头的是私有变量,不允许外部修改
self.__name = name
self.age = age
def setName(self, name):
self.__name = name
def show(self):
print(self.__name)
print(self.age)
zs = Student('Zhang San', 13)
zs.age = 14
zs.setName('Li si')
zs.show()
获取一个对象的所有属性和方法
print(dir(object))
# 也可以使用help方法获取一些第三方的对象或方法的帮助信息
print(help(object))
print(help(object.method))
对象属性相关方法
class Dog(object):
def __init__(self, name, age):
self.__name = name
self.age = age
def show(self):
print(self.__name)
dog = Dog('狗子', 13)
print(hasattr(dog, 'name'))
print(hasattr(dog, 'age'))
print(setattr(dog, '__name', 'fff'))
print(getattr(dog, '__name'))
print(hasattr(Dog, 'show'))
类属性
类属性可以被所有实例使用,如果实例属性和类属性重名,实例属性的优先级更高
class Dog(object):
name = '狗蛋'
d = Dog()
print(d.name)
print(Dog.name)
动态绑定对象方法
from types import MethodType
class Student(object):
pass
s = Student()
def setAge(self, age):
self.age = age
s.setAge = MethodType(setAge, s)
s.setAge(25) # 动态绑定对象方法,只对当前对象有效
print(s.age)
s1 = Student()
s1.setAge(22) # 报错
动态绑定类方法
class Student(object):
pass
s = Student()
def setAge(self, age):
self.age = age
Student.setAge = setAge
s.setAge(33)
print(s.age)
插槽
__slots__
是一个类变量,用于限制类的实例可以拥有的属性。当你定义了一个类时,可以在类的内部声明一个名为__slots__
的变量,它是一个包含字符串的元组,每个字符串代表一个允许的属性名称
使用__slots__
的主要目的是节省内存。当你创建类的实例时,Python会为每个实例分配一定的内存空间来存储属性
如果你给一个类定义了__slots__
,Python就会限制实例只能拥有__slots__
中列出的属性,而不是为每个实例动态地分配内存空间。这样可以减少内存的使用,提高性能
from types import MethodType
class Student(object):
__slots__ = ('name', "age", "setAge")
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print(self.name, self.age)
s = Student('张三', 13)
s.name = '李四'
def setAge(self, age):
self.age = age
s.setAge = MethodType(setAge, s)
s.setAge(35)
s.show()
s.score = 99 # 不在 __slots__ 范围内的属性或方法不允许动态绑定
property
通过 property 来实现 getter setter
class Student(object):
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, year):
self._birth = year
@property
def age(self):
return 2020 - self._birth
s = Student()
s.name = '张三'
s.birth = 1987
s.age = 100 # age是只读的,不可设置
print(s.name, s.birth, s.age)
多重继承
Python 使用 MixIn 设计来实现多重继承,使用起来很简单
# 狗 分别继承了 动物类 和 能跑类
class Dog(Animal,Runable):
pass
子类调用父类
多重继承下的子类调用父类
这种方式的优点是可以支持多重继承,但是A类会被重复实例化
class A(object):
def __init__(self):
print("A init")
class B(A):
def __init__(self):
A.__init__(self)
print("B init")
class C(A):
def __init__(self):
A.__init__(self)
print("C init")
class D(B, C):
def __init__(self):
print("D init")
B.__init__(self)
C.__init__(self)
d = D()
更建议从设计上避免使用多重继承,然后用super来实现子类调用父类,这样的话基类不会被重复实例化
class A:
def __init__(self):
print("A init")
def test(self):
print("A test")
class B(A):
def __init__(self):
super(B, self).__init__()
print("B init")
super(B, self).test()
b = B()
魔术方法
__str__
print对象时自定义输出(方法中返回的字符串)__repr__
交互式解释器自定义输出(方法中返回的字符串),如果__str__
没有定义,会调用__repr__
__iter__
使对象可迭代,返回一个迭代对象,如:return iter([1, 2, 2, 3, 4, 5])__next__
迭代到下一个值__getitem__
像list那样使用对象, obj()[2],接收一个索引参数__setitem__
obj()[2]=22,接收两个参数:key, value__delitem__
删除一个元素,del obj()[2],接收一个索引参数__getattr__
当调用不存在的属性时触发,接收一个参数__dict__
默认会返回所有属性的键值对字典,对对象进行Json序列化的时候可以使用__call__
像函数那样直接调用对象时触发object(),跟php的__call不一样(php是调用一个不存在的方法时触发)
枚举类
from enum import Enum, unique
# 枚举类,默认从1开始
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
print(Month.Jan.name)
print(Month.Jan.value)
# 遍历枚举类
for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)
# 自定义枚举类的数值
@unique
class Month2(Enum):
Jan = 3
Feb = 4
Mar = 5
Apr = 6
May = 7
Jun = 8
Jul = 9
Aug = 10
Sep = 11
Oct = 12
Nov = 13
Dec = 14
print(Month2.Jan.name)
print(Month2.Jan.value)
动态创建类
通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class
def fn(self, text):
print(text)
# 参数1:class的名称
# 参数2:继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法
# 参数3:class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上
Hello = type('Hello', (object,), dict(hello=fn))
h = Hello()
h.hello('ss')