組合,反射,魔術方法 組合 反射 魔術方法 組合 什麼是組合? 組合就是,一個對象擁有一個屬性,該屬性的值是另外一個對象. """什麼場景下使用繼承? 什麼場景下使用組合?""" 繼承一般情況用在:什麼是什麼的情況 is 組合一般用在:什麼有什麼的情況 has class Foo: def __in ...
組合,反射,魔術方法
- 組合
- 反射
- 魔術方法
組合
什麼是組合?
組合就是,一個對象擁有一個屬性,該屬性的值是另外一個對象.
"""什麼場景下使用繼承? 什麼場景下使用組合?"""
繼承一般情況用在:什麼是什麼的情況 is
組合一般用在:什麼有什麼的情況 has
class Foo:
def __init__(self, m):
self.m = m
class Bar():
def __init__(self, n):
self.n = n
"""一個對象擁有一個屬性,該屬性的值是另外一個對象."""
obj=Bar(10)
obj1 = Foo(20)
# 超級對象,通過一個屬性可以訪問到另外一個對象的值
obj.x=obj1
print(obj.x.m)
案例
組合案例:選課
class People():#父類
school = 'SH'
def __init__(self, name, age, gender, course_name=None, course_price=None, course_period=None):
self.name = name
self.age = age
self.gender = gender
# self.course_name = course_name
# self.course_price = course_price
# self.course_period = course_period
class Admin(People):#管理員
def __init__(self, name, age, gender):
super().__init__(name, age, gender)
class Course():#科目
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
python=Course('python', 10000, '6mon')#添加科目
linux=Course('linux', 20000, '5mon')
# print(python.name)
# print(python.price)
# print(python.period)
class Student(People):
#學生
def __init__(self, name, age, gender, course=None):
super().__init__(name, age, gender)
if course is None:
course = []
self.course = course
stu = Student('kevin', 20, 'male')
stu.course.append(python.name)#進行組合
stu.course.append(linux.name)#組合
print(stu.course) # [<__main__.Course object at 0x000001F258F86B80>, <__main__.Course object at 0x000001F258F511C0>]
# stu.course: []
for i in stu.course:
print(i)
class Teacher(People):#老師
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender)
self.level = level
tea = Teacher('ly', 19, 'female', 10)
# print(tea.course_name)
tea.course=linux#創建一個course,將linux組合
print(tea.course.period)
print(tea.course.name)
print(tea.course.price)
反射
在Python中,反射指的是通過字元串來操作對象的屬性,涉及到四個內置函數的使用(Python中一切皆對象,類和對象都可以用下述四個方法)
四個內置函數:
getattr: 獲取屬性 ##### 用的最多
setattr:設置屬性
hasattr:判斷是否有某個屬性
delattr:刪除
getattr 獲取屬性
class Student():
school = 'SH'
def __init__(self,name, age):
self.name=name
self.age = age
def func(self):
print('from func')
def index(self):
print('from index')
stu = Student('kevin', 20)
# attr=input('請輸入你要操作的屬性名:')
"""反射:就是通過字元串的形式來操作對象的屬性"""
# 1. 獲取屬性
"""當你查詢的屬性不存在的時候,如果給了第三個參數,就返回第三個參數"""
print(stu.school)
res = getattr(stu, 'school1', 666)
print(res)
res1=getattr(stu,'shool',666)
print(res1)#666
res2=getattr(stu,'name')
print(res2)
### 函數的用法
"""必須掌握!!!!!!"""
res=getattr(stu, 'func1', stu.index)#等同於stu.func1,不存在該屬性則返回預設值stu.index
res()
setattr:設置屬性
### 設置
class Student():
school = 'SH'
def __init__(self,name, age):
self.name=name
self.age = age
def func(self):
print('from func')
def index(self):
print('from index')
stu = Student('kevin', 20)
setattr(stu, 'x', 666) # stu.x=666
print(stu.__dict__)#{'name': 'kevin', 'age': 20, 'x': 666}
hasattr:判斷是否有某個屬性
#判斷
class Student():
school = 'SH'
def __init__(self,name, age):
self.name=name
self.age = age
def func(self):
print('from func')
def index(self):
print('from index')
stu = Student('kevin', 20)
print(hasattr(stu, 'func'))#True
print(hasattr(stu,'qwe'))#False
if hasattr(stu, 'func'):
getattr(stu, 'func')()
else:
pass
delattr:刪除
class Student():
school = 'SH'
def __init__(self,name, age):
self.name=name
self.age = age
def func(self):
print('from func')
def index(self):
print('from index')
stu = Student('kevin', 20)
delattr(stu, 'name')
print(stu.__dict__)#{'age': 20}
魔術方法
init str,repr
class Student():
def __init__(self, name, age):
self.name = name
self.age = age
"""
1. 列印對象的時候,輸出對象的時候會自動觸發類中得__str__方法
2. 返回值必須是字元串形式
3. 如果它跟__repr__方法同時存在,__str__的優先順序更高
"""
def __str__(self): # 這個用的是最多的
print('str')
return 'from str'
def __repr__(self):
print('repr')
return 'from repr'
wqe=Student('qwe',12)
print(wqe)#str from str
# print('repr:', repr(wqe))
print('str:', str(wqe))#str str: from str
del
class MySQL:
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.f = open('a.txt', 'w')
"""
1.當你刪除對象的時候會觸發__del__的執行
2. 當整個腳本的程式都執行完畢的時候,也會觸發__del__的執行
3. 一般用在用來在對象被刪除時自動觸發回收系統資源的操作
"""
def __del__(self):
print('from _del')
self.f.close()
mysql = MySQL('127.0.0.1', 3306)
issubclass方法用於判斷參數 class 是否是類型參數 classinfo 的子類
class Foo:
pass
class Bar(Foo):
pass
class Bar1():
pass
print(issubclass(Bar1, Foo))
__doc__註釋無法繼承
class Foo:
"""
'我是描述信息asdasd'
'我是描述信息asdasd'
'我是描述信息asdasd'
"""
pass
class Bar(Foo):
pass
print(Foo.__doc__)
# '我是描述信息asdasd'
# '我是描述信息asdasd'
# '我是描述信息asdasd'
print(Bar.__doc__)
#None
enter和exit 上下文管理器with原理
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變數')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代碼塊執行完畢時執行我啊')
"""with它可以用在很多地方,但是,出現with語句後面的對象中得類必須要聲明__enter__和__exit__"""
with Open('a.txt') as f:
print('=====>執行代碼塊')
print('=====>執行代碼塊')
print('=====>執行代碼塊')
print('=====>執行代碼塊')
print('=====>執行代碼塊')
# print(f,f.name)
簡答題:先聊聊with 的用法? 問with上下文管理協議的執行原理? 為什麼打開文件只會可以自動關閉?請說出原因
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變數')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代碼塊執行完畢時執行我啊')
print(exc_type) # 異常類型
print(exc_val) # 異常值
print(exc_tb) # 追溯信息
return True # 如果你在這個方法裡面返回了True,with代碼塊中出現了異常,就相當於沒有出現異常
"""with它可以用在很多地方,但是,出現with語句後面的對象中得類必須要聲明__enter__和__exit__"""
# with Open('a.txt') as f:
# print('=====>執行代碼塊')
# print('=====>執行代碼塊')
# print('=====>執行代碼塊')
# print('=====>執行代碼塊')
# print('=====>執行代碼塊')
# # print(f,f.name)
"""如果with代碼塊中出現了異常,則with語句之後的代碼都不能正常執行"""
with Open('a.txt') as f:
print('=====>執行代碼塊')
raise AttributeError('***著火啦,救火啊***') # 拋出異常,主動報錯
print('0'*100) #------------------------------->不會執行
setattr 設置 ,delattr 刪除,getattr查看
點語法
__setattr__,__delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y=y
"""當你找的屬性不存在的時候,會觸發__getattr__,但是必須是點語法的時候才會"""
def __getattr__(self, item):
print('----> from getattr:你找的屬性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value # self.a=20
# self.key=value #這就無限遞歸了,你好好想想
self.__dict__[key]=value #應該使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #無限遞歸了
self.__dict__.pop(item)
obj=Foo(10)
# obj.z
obj.a=20
print(obj.a)
del obj.a
setitem,getitem,delitem__
中括弧取值時
__setitem__,__getitem,__delitem__
class Foo:
def __init__(self, name):
self.name = name
"""當你通過中括弧獲取對象的屬性的時候,會自動觸發__getitem__"""
def __getitem__(self, item):
print('__getitem__')
print(self.__dict__[item])
def __setitem__(self, key, value):
# key:age
# value:18
print('__setitem__')
self.__dict__[key] = value
# self.__dict__['age'] = 18
def __delitem__(self, key):
print('del obj[key]時,我執行')
self.__dict__.pop(key)
pass
# def __delattr__(self, item):
# print('del obj.key時,我執行')
# self.__dict__.pop(item)
obj=Foo('tom')
# print(obj.name)
# obj['name']
obj['age'] = 18
# obj.age=18
print(obj.age)
del obj['age']
call
class Foo:
def __init__(self):
pass
#### 當對象加括弧的時候會觸發__call__的執行
def __call__(self, *args, **kwargs):
print('__call__',*args)
obj=Foo()
print(obj)#<__main__.Foo object at 0x000002CCFDE2BF70>
obj('qe')#__call__ qe