文章目录
类属性
生活中总会出现这样一种特征,一类事物共有的共同的特征,Python语法中提供了类型属性(简称类属性)描述表现这样的特征。
什么是类属性
定义给类型的属性,直接描述一类事物的特征,而不是具体某个对象的特征。
类属性的声明
类属性,声明在类型的内部,方法的外部。
class Person:
"""人的类型"""
# 类属性
max_age = 150
def __init__(self, name, age):
self.name = name
self.age = age
类属性的特点
类属性描述了一类事物的特征,所以可以被这个类型创建的所有对象去访问(不能修改)
类属性的访问及修改
class Person:
max_age = 150
def __init__(self, name, age):
self.name = name
self.age = age
# 类属性的访问
# 1. 通过 类名.类属性 访问
>>> print(Person.max_age)
150
# 2. 通过 对象.类属性 访问
>>> man = Person("tom", 35)
>>> man.max_age
150
# 类属性的修改
# 通过 类名.类属性 修改
>>> Person.max_age = 130
>>> print(Person.max_age)
130
类属性的适用场景
类属性的出现,主要是用来描述一类事物共同的特征,如果在项目开发中,出现了类似的特征,要求所有对象都能遵循满足同一个特征数据,考虑适用类属性声明这个特征!
类方法
基本语法
class 类型名称:
...
@classmethed
def 类方法名称(cls, [形参]):
pass
- 类方法,也是一种方法,遵循方法的命名规范
- 类方法,需要在方法上边加上
@classmethed
装饰器声明,表示这是一个类方法 - 类方法,第一个参数
cls
表示的是当前类 - 类方法可以访问和修改类属性,通过
cls
直接访问和修改
类方法的调用执行
类方法和类属性一样,推荐直接通过 类名.方法名调用执行
类方法属于一类事物的共同行为,所以通过对象也可以调用
什么时候声明类方法
项目中的某个类型出现了一种行为,和具体的对象无关,此时这样的行为方法,就可以被声明为类方法。
类属性的封装,属性的 set/get 方法必须通过类方法来实现
静态方法
基本语法
class 类名:
...
@staticmethod
def get_current_time():
return datatime.now()
什么时候声明静态方法
项目开发过程中,出现了一些功能性的方法,如获取当前系统时间,如此简单之行为,抽取对象声明类型,反倒有过度设计的嫌疑!
注意:面向对象的开发中,不要为了面向对象去专门强行设计类型,很容易造成过度设计!
1. 声明函数实现
面向对象的项目中,如果出现了一些实现独立的小功能行为,可以将这样的功能声明成函数在项目中调用执行(面向过程 面向对象 混合开发)
- 优点:函数式的实现,开发过程中适用方便,哪里需要哪里声明哪里调用!
- 缺点:如果没有足够的项目规范约束,项目中声明的多个函数到处都是不好维护!
2. 静态方法实现
类似获取时间这样的功能性函数,如果抽取对象声明类型比较繁琐,Python语法中针对这样的函数提供了一个特殊的方法:静态方法。包含在任意一个类型中,通过类型统一管理,可以通过类型名称直接调用,但是静态方法不能访问实例属性,也不能访问类型属性,只起到了函数的作用!
静态方法深入浅出
- 静态方法声明在类型中,使用
@staticmethod
声明 - 静态方法既不能访问实例属性,也不能访问类属性,只起到函数的作用
- 静态方法推荐通过 类名调用执行
- 如果一个方法既不访问对象数据也不访问类数据,考虑使用静态方法
小结
实例方法 | 类方法 | 静态方法 | |
---|---|---|---|
访问实例属性 | Y | N | N |
访问类属性 | Y | Y | N |
魔法方法
什么是魔法方法
魔法方法如同它的名字一样神奇,是指哪些Python内部已经包含的,被双下划线所包围的方法,这些方法在进行特定的操作时会被自动调用。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
"""当对象被打印时调用"""
return f"name is {self.name}, age is {self.age}"
tom = Person("tom", 18)
print(tom)
# name is tom, age is 18
基础魔法方法
魔法方法名 | 描述 |
---|---|
new(cls) | 构造方法 |
init(self) | 初始化方法 |
call(self[,…]) | 允许一个对象像函数一样被调用:x(a,b) 调用x.__call__(a,b) |
len(self) | 定义当被len() 调用时的行为 |
repr(self) | 定义当被repr() 调用时的行为 |
str(self) | 定义当被str() 调用时的行为 |
hash(self) | 定义当被hash() 调用时的行为 |
属性相关
魔法方法名 | 描述 |
---|---|
getattr(self,name) | 定义一个当用户试图获取一个不存在的属性时的行为 |
getattribute(self, name) | 定义当该类的属性被访问时的行为 |
setattr(self, name, value) | 定义当一个属性被设置时的行为 |
delattr(self, name) | 定义当一个属性被删除时的行为 |
dir(self) | 定义当 dir() 被调用时的行为 |
比较操作符
魔法方法名 | 描述 |
---|---|
lt(self, other) | 定义小于号的行为:x < y 调用 x.__lt__(y) |
eq(self, other) | 定义等于号的行为:x == y 调用 x.__eq__(y) |
ne(self, other) | 定义不等号的行为:x != y 调用 x.__ne__(y) |
gt(self, other) | 定义大于号的行为:x > y 调用 x.__gt__(y) |
算术运算符
魔法方法名 | 描述 |
---|---|
add(self, other) | 定义加法的行为:+ |
sub(self, other) | 定义减法的行为:- |
mul(self, other) | 定义乘法的行为:* |
truediv(self, other) | 定义真除法的行为:/ |
增量赋值运算
魔法方法名 | 描述 |
---|---|
iadd(self, other) | 定义赋值加法的行为:+= |
isub(self, other) | 定义赋值减法的行为:-= |
imul(self, other) | 定义赋值乘法的行为:*= |
itruediv(self, other) | 定义赋值真除法的行为:/= |
类型转换
魔法方法名 | 描述 |
---|---|
int(self) | 让当前对象支持 int() 类型转换操作 |
float(self) | 让当前对象支持 float() 类型转换操作 |
bool(self) | 让当前对象支持 bool() 类型转换操作 |
str(self) | 让当前对象支持 str() 类型转换操作 |
… more and more
反射方法
什么是反射方法
反射方法,就是不通过方法名称调用方法,而是通过一个字符串反向解析得到方法对象执行方法的过程。
# 常规
Object.study() # 执行了 study() 方法
# 反射
method = getattr(Object, "study")
method()
常见的反射方法
魔法方法名 | 描述 |
---|---|
hasattr(obj, attr) | 判断目标对象中是否包含指定的属性或者方法 |
getattr(obj, attr) | 从目标对象中获取执行名称的属性或者方法 |
setattr(obj, attr, value) | 获取并执行目标对象中的属性或者方法 |
delattr(obj, attr) | 从目标对象中删除对应的属性或者方法 |