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)