class Student:
def __init__(self, name, tel, study_id='001', score=0):
self.name = name
self.tel = tel
self.study_id = study_id
self.score = score
# 在打印一个对象的时候,系统会自动用这个对象去调用__repr__方法,并且获取这个方法的返回值
# 返回值是什么就打印什么(返回值必须是字符串)
def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}>'
# __dict__将对象转换成字典
stu1 = Student('小王', 123456, '0001', 1)
stu2 = Student('小林', 22222, '0002', 12)
print(stu1) # <'name': '小王', 'tel': 123456, 'study_id': '0001', 'score': 1>
# 对象属性的增删改查
# 查---获取对象的属性值
'''
对象.属性
getattr(对象,属性名) 可以做到动态获取属性值
'''
print(stu1.name) # 小王
# value=input('请输入要获取的属性名:')
# print(getattr(stu2,value)) # value="name" 小林 value="tel" 22222
print(getattr(stu2, 'height', 180)) # 180 获取不存在的属性如果不给默认值会报错,
# 增/改
'''
对象.属性=值 属性存在的时候就是修改,属性不存在的时候就是增加
setattr(对象,属性名,值) 可以做到动态增加/修改属性值
'''
stu1.name = '我不是小王'
stu1.height = '新添加的属性:身高170'
print(stu1) # <'name': '我不是小王', 'tel': 123456, 'study_id': '0001', 'score': 1, 'height': '新添加的属性:身高170'>
setattr(stu1, 'name', '我还是小王')
print(stu1) # <'name': '我还是小王', 'tel': 123456, 'study_id': '0001', 'score': 1, 'height': '新添加的属性:身高170'>
# 删
'''
del 对象.属性 删除属性
del 对象 删除对象
delattr(对象,属性名)
'''
del stu1.height
print(stu1) # <'name': '我还是小王', 'tel': 123456, 'study_id': '0001', 'score': 1>
delattr(stu1, 'study_id')
print(stu1) # <'name': '我还是小王', 'tel': 123456, 'score': 1>
对象方法:
定义:直接定义
调用:对象.方法名()
特点:有个默认参数self,这个参数在调用的时候不用传参,系统会自动将当前对象传给self
使用:如果实现函数的功能需要用到对象,那么这个函数就定义成对象方法
类方法:
定义:在定义函数前加@classmethod
调用:类.方法名()
特点:有个默认参数cls,这个参数在调用的时候不用传参,系统会自动将当前类传给cls
使用:如果实现函数的功能不需要对象需要用到类,那么这个函数就定义成类方法
静态方法
定义:在定义函数前加@staticmethod
调用:类.方法名()
特点:没有默认参数
使用:实现函数功能不需要对象也不需要类的前提下就定义静态方法
class Student:
# func1是对象方法
def func1(self):
print('对象方法')
# func2是类方法
@classmethod
def func2(cls):
print('cls:', cls) # cls:<class '__main__.Student'>
# 当前类能做的,cls都可以做
# func3是静态方法
@staticmethod
def func3():
print('静态方法')
print('Student:', Student) # Student: <class '__main__.Student'>
class Person:
"""
人类
"""
num = 61
def __init__(self, name='张三', age=18, gender='男'):
self.name = name
self.age = age
self.gender = gender
def eat(self, food='面条'):
print(f'{self.name}在吃{food}')
@classmethod
def message(cls):
print(f'人类目前的数量是:{cls.num}')
@staticmethod
def destroy():
print('人类破坏环境')
p1 = Person()
# 类属性
'''
类名.__doc__ 获取类的说明文档
print(Person.__doc__) # 人类
类名.__module__ 获取指定类所在的模块 如果结果是__main__ 说明是当前模块
print(Person.__module__) # __main__
print(list.__module__) # builtins
对象.__class__ 获取指定对象对应的类型,和type(对象)功能一样
print(p1.__class__) # <class '__main__.Person'>
print(type(p1)) # <class '__main__.Person'>
类名.__name__ 获取类名类型为str
print(Person.__name__) # 'Person'
print(int.__name__) # 'int'
类名.__dict__ 获取类所有的字段和字段值,转化为字典,key是字段名,value是字段的值
print(Person.__dict__)
对象.__dict__ 获取对象所有的属性和属性值,转化为字典,key是属性名,value是属性的值
print(p1.__dict__) # {'name': '张三', 'age': 18, 'gender': '男'}
类名.__base__ 获取指定类的父类
类名.__bases__ 获取类所有的父类
object是python中所有类的基类
print(Person.__base__) # <class 'object'>
print(Person.__bases__) # (<class 'object'>,)
'''
# 根据数据不同的类型创建以该类型名命名的文件
datas = ['abc', -0.1234, '你好', 564]
for data in datas:
with open(rf'files\{data.__class__.__name__}.txt', 'a', encoding='utf-8') as f:
f.write(str(data) + '\n')
getter
使用:在获取对象属性前,如果要做别的什么事就可以给这个属性添加getter
用法:
在需要添加getter的属性名前加_
在装饰器@property后面定义一个函数,函数名就是属性名去掉_
函数没有参数,但是需要一个返回值,返回值就是获取属性值得到的结果
通过对象获取属性的时候,属性不需要带_
class Circle:
pi = 3.14
def __init__(self, r=10):
self.r = r
@property
def area(self):
return Circle.pi * self.r ** 2
c1 = Circle(100)
print(c1.area)
练习,给Person添加属性,要求:age中保存年龄值,但是获取age属性的时候
得到的是:儿童(0-4),少年(5-12),青年(13-28),壮年(29-40)中年(41-55),老年(55以上)
class Person:
def __init__(self, age=0, name='张三', gender='男'):
self.name = name
self._age = age
self.gender = gender
@property
def age(self):
if 0 <= self._age <= 4:
return '儿童'
elif 5 <= self._age <= 12:
return '少年'
elif 13 <= self._age <= 28:
return '青年'
elif 29 <= self._age <= 40:
return '中年'
else:
return '老年'
setter —添加之前必须添加getter
’
给对象属性赋值的之前做别的事情,就给这个属性添加setter
用法
在装饰器 @函数名.setter 后面定义一个函数,函数名就是属性名去掉_
函数有且只有一个参数(这个参数指向的是赋值的时候赋的值)
@age.setter
def age(self, value):
print(value)
if type(value) != int:
raise ValueError
if value < 0 or value > 150:
raise ValueError
p1 = Person()
# p1.age='dwa' ValueError
# p1.age=151 ValueError
访问权限
公开的:公开的属性和方法在类的内部外部都能用,并且可以被继承
保护的:保护的属性和方法在类的内部可以使用,外部不能用,但是可以继承
私有的:私有的属性和方法在类的内部可以使用,外部不能用,不能被继承
python中的属性和方法只有访问权限:公开的
python 所谓的私有化只是一种说明提示
私有化的方法:
在属性名和方法名前加__(只能是两个__开头,不能再__结尾)
class Person:
num = 100
__info = '动物'
def __init__(self, name='张三', age=18, gender='男'):
self.name = name
self.age = age
self.gender = gender
def func1(self):
return Person.__info
def __func2(self):
return Person.num
p1 = Person()
print(p1.func1()) # 动物
print(Person.num) # 100
# print(Person.__info) # AttributeError: type object 'Person' has no attribute '__info'
# print(p1.func2()) # AttributeError: 'Person' object has no attribute 'func2'
# print(Person._Person__info) # 动物 强行查看
运算符
python在使用运算符的时候,本质是在调用运算符对应的方法
每个运算符对应的方法的方法名是固定的,不同类型的数据在参与相同运算的时候
会调用不同类中对应方法
某个类型的数据是否支持某种运算,就看这个数据对应的类型中有没有实现这个运算符对应的方法
# __add__
class Person:
def __init__(self, age=0, name='?', gender='男'):
self.name = name
self._age = age
self.gender = gender
#self指向+前面的数据,other指向+后面的数据
def __add__(self, other):
return self.name + other.name
def __mul__(self, other):
return [self.name for _ in range(len(other.name))]
def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}>'
def __gt__(self, other1):
return self._age>other1._age
p1 = Person(56,'王五','男')
p2 = Person(1, "小花",'女')
print(p1 + p2) # 张三李四 本质是:pi.__add__(p2)
print(p1 * p2) # ['张三', '张三'] 本质是:pi.__mul__(p2)
# 练习 根据年龄排序
p3=Person(20,'张三','男')
p4=Person(25,'老王','男')
# 方法一 重载 > 运算符
ps=[p1,p2,p3,p4]
print(sorted(ps))
# 方法二 实参高阶函数
ps.sort(key=lambda item :item._age)
print(ps)