Day 15
面向对象2
对象属性操作
- 查 – 获取对象属性的值
语法:
1)对象.属性名 – 属性名不存在时会报错
2)getattr.(对象,‘属性名’) – 注意:属性名要用’’引起来;在属性名后面加一个参数表示默认值,在属性名不存在时返回默认值
- 增和改 – 添加或修改对象属性
语法:
1)对象.属性名 = 值 – 属性名存在时会修改;属性值不存在时会添加
2)setattr(对象,‘属性名’,值) – 同上
- 删 – 删除对象属性
语法:
1)del 对象 – 删除对象
2)del 对象.属性名 – 删除对象属性
3)delattr(对象,‘属性名’) – 删除对象属性
类方法和静态方法
类方法
- 定义:
在定义函数前加一个@classmethod装饰器
- 使用:
类.方法名(),默认参数cls,这个参数在调用时不用传参,系统会自动将当前类传给cls;cls类似对象方法中的参数self,类具有的功能参数cls都具有
- 使用情景:
实现函数功能在不需要对象属性的前提下需要使用类,定义函数时使用类方法
静态方法
- 定义:
在定义函数前加一个装饰器@staticmethod
- 使用:
类.方法名(),没有默认参数,相当于一个普通函数
- 使用情景:
实现函数功能时既不需要对象也不需要使用类,定义函数时使用静态方法
内置类属性
-
常用的内置类属性
-
1)类.
doc
获取类的说明文档 -
2)类.
module
获取指定类所在的模块 -
3)类.
name
获取指定类名 -
4)类.
class
获取指定对象对应的类型,和type(对象)功能一致 -
5)类.
dict
or 对象.
dict
将类转换为字典,key是字段名,value为字段对应的值
将对象转换为字典,key是字段属性名,value为属性值 -
6)类.
base
获取指定类的父类
类.
bases
获取指定类的所有父类
-
1)类.
print(Person.__doc__)
print(str.__doc__)
print(Person.__module__) # __main__:表示类就在当前模块下
print(list.__module__) # builtins:系统模块所在位置
print(Person.__name__) # Person
print(id.__name__) # id
print(p1.__class__) # <class '__main__.Person'>
print(type(p1)) # <class '__main__.Person'>
print(Person) # <class '__main__.Person'> 对比Person.__name__
print('a'.__class__) # <class 'str'>
print((10).__class__) # <class 'int'>
class Person:
"""
人类
"""
num = 61
def __init__(self, name=None, age=None, gander=None):
self.name = name
self.age = age
self.gander = gander
def eat(self, food=None):
print(f'{self.name}在吃{food}')
@classmethod
def messsage(cls):
print(f'人类目前的数量为:{cls.num}')
p = Person()
print(Person.__dict__) # 从结果来看,定义函数就是在定义变量(方法也是属性)
print(p.__dict__) # 获取对象的全部属性
print(dict.__bases__)
getter和setter
getter
- 使用情景:
在获取对象属性之前如果需要其他操作,就给这个属性添加getter
- 使用:
1.在需要添加getter的属性的属性名前加_
2.在@property装饰器后面定义一个函数(相当于定义一个对象属性)函数名就是属性名去掉_,函数没有其他参数,返回值为获取这个属性真正得到的结果
3.通过对象获取属性的时候,属性不属于带_
lass Circle:
pi = 3.1415926
def __init__(self, radius=1):
self.radius = radius
# self._area = Circle.pi * (radius << 1)
@property
def area(self):
return Circle.pi * (self.radius << 1)
c1 = Circle()
print(c1.area)
c1.radius = 2
print(c1.area)
setter
- 使用情景:
如果要在给某个对象属性赋值之前有其他操作,就给这个属性添加setter,且在添加setter之前必须添加getter
- 使用:
1.在需要添加getter的属性名前加-
2.在名为@添加getter的属性名.setter的装饰器后面定义一个函数,函数名为添加getter的属性名去掉_,函数有一个参数(指向赋值时赋予的值),没有返回值
3.最终目的是给属性赋值,通过对象给属性赋值时,属性名不需要加_
class PersonPro:
"""
年龄状态
"""
def __init__(self, age=None):
self._age = age
@property
def age(self):
if 0 <= self._age <= 4:
return '儿童'
elif self._age <= 12:
return '少年'
elif self._age <= 28:
return '青年'
elif self._age <= 40:
return '壮年'
elif self._age <= 55:
return '中年'
else:
return '老年'
@age.setter
def age(self, value):
print(f'value:{value}')
if type(value) != int:
raise TypeError
if value < 0 or value > 220:
raise ValueError
self._age = value
p2 = PersonPro()
p2.age = 300
print(p2.age)
私有化
访问权限
- 公开的:公开的属性和方法在类内部和外部都能使用,并且可以被继承
- 保护的:保护的属性和方法在类的内部可以使用,在外部不能使用,但可以继承
- 私有的:私有的属性和方法在类的内部和外部都不能使用,且不能被继承
Python对权限的管理
Python中所有的属性和方法只有公开的;所谓的私有化其实是伪私有,仅仅只是一个私有声明
-
注意:
尽管我们可以通过方法来访问到Python中的私有化内容,但作为一名程序员,相对的规则就一定要遵守
私有化方法
在属性名和方法名前加__(注意:只需要两个下划线开头,不需要结尾)
运算符重载
Python在使用运算符时实质实在调用运算符对应的魔法方法
每个运算符对应的方法的方法名是固定的
不同类型数据在参与相同运算符的运算时,运算符调用的方法是不同的
某个类型的数据是否支持某种运算就看这个数据对应的类型中有没有实现这个运算符对应给功能