程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Xiaobai learns python series————【Day45】Object-oriented magic method and metaclass in detail

編輯:Python

今日內容概要

  • 反射實戰案例
  • object-oriented magic(雙下方法)
  • Practical practice of magic methods
  • Introduction to Metaclasses
  • 創建類的兩種方式
  • Practical applications of metaclasses
  • Meta class double downnew方法

反射實戰案例

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)

Object-oriented magic methods

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

Magic method written test questions

需求:補全下面代碼,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()

Introduction to Metaclasses

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“元類!!!”

Two ways to generate classes

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__.

double magic methodnew方法

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'} '''

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved