1.實戰一:Load configuration file with pure uppercase configuration
# 配置文件加載:Get all uppercase configs in the config file 小寫的直接忽略 組織成字典 import settings new_dict = { } # print(dir(settings)) # dirGet the callable name of the object in parentheses # ['AGE', 'INFO', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'desc', 'name'] for i in dir(settings): if i.isupper(): # If the name is uppercase Then get the value corresponding to the capitalized name 'AGE' 'INFO' v = getattr(settings, i) new_dict[i] = v print(new_dict)
2.實戰二:模擬操作系統cmdTerminal executes user commands
class WinCmd(object): def dir(self): print('dir獲取當前目錄下所有的文件名稱') def ls(self): print('lsGet the names of all files in the current path') def ipconfig(self): print('ipconfigFor information on the current computer network card') obj = WinCmd() while True: cmd = input('請輸入您的命令>>>:') if hasattr(obj, cmd): cmd_name = getattr(obj, cmd) cmd_name() else: print('%s 不是內部或外部命令,也不是可運行的程序或批處理文件' % cmd)
1.Magic method concept
Magic methods is under the dual methods defined in class,The reason why they are called magic methods is that these methods are automatically triggered when a certain condition is reached.,無需調用.
eg:__init__The method is automatically triggered when unique data is set to the object.(實例化)
2.Common magic methods and trigger conditions
(1)__init__
class MyClass(object): def __init__(self,name): """Triggered automatically when an object is instantiated""" print('__init__方法') obj = MyClass
(2)__str__
class MyClass(object): def __str__(self): """ Triggered automatically when the object is printed 該方法必須返回一個字符串 What string is returned and what string is displayed after printing the object """ # print('__str__方法') print('這是類:%s 產生的一個對象') # return '對象:%s'%self # return '對象:%s'%self return '' obj = MyClass() print(obj)
(3)__call__
class MyClass(object): def __call__(self, *args, **kwargs): """object call with parentheses trigger the method automatically""" print('__call__方法') print(args) print(kwargs) obj = MyClass() obj(1,2,name='jaosn',age = 18) ''' __call__方法 (1, 2) {'name': 'jaosn', 'age': 18} '''
(4)__getattr__
class MyClass(object): def __getattr__(self, item): """When an object gets a property name that doesn't exist 自動觸發 該方法返回什麼 What does an object get when it gets a property name that doesn't exist? 形參itemIs the object to obtain attribute name does not exist """ print('__getattr__', item) return 'The property name you want to get:%s不存在' % item obj = MyClass() print(obj.age) ''' __getattr__ age The property name you want to get:age不存在 '''
(5)__setattr__
class MyClass(object): def __init__(self,name): """Triggered automatically when an object is instantiated""" print('__init__方法') self.name = name def __setattr__(self, key, value): """對象操作屬性值的時候自動觸發>>>: 對象.屬性名=屬性值""" print("__setattr__") print(key) print(value) # super().__setattr__(key, value) __str__Need to write this after rewriting obj = MyClass('jason') print(obj.__dict__) # {'name': 'jason'} obj.name = 'kevin' print(obj.__dict__) # {'name': 'kevin'}
(6)__del__
class MyClass(object): def __del__(self): """對象在被刪除(主動 被動)的時候自動觸發""" print('__del__') obj = MyClass() del obj # __del__
(7)__gatattribute__
class MyClass(object): def __getattribute__(self, item): print('__getattribute__') """Triggered automatically when an object gets a property Whether this property exists or not When the class has__getattr__又有__getattribute__的時候 only go the latter """ # supplementary back__getattr__方法: return super(MyClass, self).__getattribute__(item) 復雜寫法 return super().__getattribute__(item) # 簡便寫法 obj = MyClass() obj.name # __getattribute__ print(obj.name) # None
(8)__enter__與__exit__
class MyClass(object): def __enter__(self): """對象被withTriggered automatically when the syntax is executed 該方法返回什麼 asWhat does the variable name after the keyword get?""" print('__enter__') return 123 def __exit__(self, exc_type, exc_val, exc_tb): """對象被withThe grammar executes and runs to completionwithafter subcode 自動觸發""" print('__exit__') obj = MyClass() with obj as f: pass print(f) # 123 ''' __enter__ __exit__ '''
3.表格說明
項目 Value __ init__對象實例化的時候自動觸發__ str__object is executed for printing(print、前端展示)Triggered automatically during operation,該方法必須返回字符串類型的數據,很多時候用來更加精准的描述對象__ del__對象被執行(被動、主動)Automatically execute after delete operation__ getattr__Fired automatically when object lookup does not exist with a name__ setattr__對象在執行添加屬性Triggered automatically during operation >>> obj.變量名=變量值__ call__對象被加括號調用的時候自動觸發__ enter__對象被執行withContext management syntax starts to fire automatically ,該方法返回什麼asWhat does the variable name after the__ exit__對象被執行withFired automatically after the context management syntax ends__ getattribute__只要對象查找名字無論名字是否存在都會執行該方法,如果類中有__getattribute__方法 那麼就不會去執行__getattr__方法__ new__before the class is instantiated,The first method to be executed,Mainly used to create a completely blank object
需求:補全下面代碼,No error is reported after execution
class Context: pass with Context() as f: f.do_something()
The answer method is as follows:
class Context: def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass def do_something(self): pass with Context() as f: f.do_something()
1.Metaclass export
(1)In the basic phase we usetypeto find the data type of the data;
(2)But after learning object-oriented,Found that view is not a data type,but the class to which the data belongs;s1 = '哈哈哈 Finally got to code this afternoon!!!' l2 = [60, 80, 100, 120, 150, 200] d = { 'name': 'die show me', 'age': 18} print(type(s1)) # <class 'str'> print(type(l2)) # <class 'list'> print(type(d)) # <class 'dict'>
(3)but the type of data,In fact, the essence is to generate objects through various classes.
class str: pass h = 'hello' str('hello')
(4)我們可以理解為typeUsed to see who is the class that produced the current object
class MyClass: pass obj = MyClass() print(type(obj)) # View generated objectsobj的類:<class '__main__.MyClass'> print(type(MyClass)) # View generated objectsMyClass的類:<class 'type'>
(5)通過上述推導,得出最後結論,Custom classes are created bytype類產生的,We will call the class that produces the class“元類!!!”
1.方式一:class關鍵字
class MyClass: pass
2. 利用元類type
type(類名,類的父類,類的名稱空間)
class MyClass1: pass print(MyClass1.__dict__,MyClass1) # {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'MyClass1' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass1' objects>, '__doc__': None} <class '__main__.MyClass1'> res = type('MyClass2',(),{ }) print(res.__dict__,res) # {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'MyClass2' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass2' objects>, '__doc__': None} <class '__main__.MyClass2'> obj = res() print(obj) # <__main__.MyClass2 object at 0x00000209EA66D390>
3.類的補充
Learning metaclasses is actually mastering the process of generating classes,We can highly customize the behavior of the class during the generation of the class.
eg:
類名必須首字母大寫
The above requirements require the use of metaclasses to control the generation process of classes check in process
1.Custom specified metaclass
class MyMetaClass(type): pass """只有繼承了typeThe class can be called is a metaclass""" class MyClass(metaclass=MyMetaClass): pass """If you want to switch the metaclass of the generated class, you cannot use inheritance 必須使用關鍵字metaclass聲明"""
2.double down in metaclassinit用於實例化類
類中的__init__用於實例化對象;元類中__init__用於實例化類.
class MyMetaClass(type): def __init__(self, what, bases=None, dict=None): # print('別暈') # print('what', what) 類名 # print('bases', bases) 類的父類 # print('dict', dict) 類的名稱空間 if not what.istitle(): # print('首字母必須大寫 你會不會寫python Have you learned object-oriented? lowB') raise Exception('首字母必須大寫 你會不會寫python Have you learned object-oriented? lowB') super().__init__(what, bases, dict) class Aaa(metaclass=MyMetaClass): pass # 沒有報錯,Indicates that the instantiation of the class was successful
Metaclasses can not only control the generation process of classes,In fact, you can also control the object!!!
(1)Object parentheses are executed to generate double-under in the object classcall
(2)Class parentheses are executed to generate double-unders in the metaclass of the classcall
回想__call__方法:
對象加括號會自動執行產生該對象的類裡面的__call__,並且該方法返回什麼對象加括號就會得到什麼
推導:類加括號會執行元類的裡面的__call__該方法返回什麼其實類加括號就會得到什麼class MyMetaClass(type): def __call__(self, *args, **kwargs): print('__call__') if args: raise Exception('Parameters must be passed as keyword arguments') super().__call__(*args, **kwargs) class MyClass(metaclass=MyMetaClass): def __init__(self, name, age): self.name = name self.age = age print('__init__') # 需求:實例化對象 All parameters must be in the form of keyword arguments obj = MyClass('jason', 18) # obj = MyClass(name='jason', age=18)
總結:
If we want to highly customize the object generation process:Can operate on the metaclass__call__.
If we want to highly customize the class generation process:Can operate on the metaclass__init__.
1.類產生對象的步驟
(1)產生一個空對象
(2)自動觸發__init__方法實例化對象
(3)返回實例化好的對象
2. __new__和__init__
__new__方法專門用於產生空對象 骨架
__init__方法專門用於給對象添加屬性 血肉
1.Customize the dictionary and let the dictionary have
d.key = value 修改鍵值對
d.key = value 添加鍵值對
class MyClass(dict):
def __setattr__(self, key, value):
self[key] = value
super().__setattr__(key, value)
obj = MyClass()
obj.name = 'k'
obj.age = 18
obj.gender = 'male'
print(obj)
''' {'name': 'k', 'age': 18, 'gender': 'male'} '''