1. 程式人生 > >python3全棧開發-內置函數補充,反射,元類,__str__,__del__,exec,type,__call__方法

python3全棧開發-內置函數補充,反射,元類,__str__,__del__,exec,type,__call__方法

庫類 instance name 元類 內置函數 port div .py peer

一、內置函數補充

1、isinstance(obj,cls)檢查是否obj是否是類 cls 的對象

class Foo(object):
  pass
obj = Foo()                 
print(isinstance(obj, Foo))  #結果為True

2、issubclass(sub, super)檢查sub類是否是 super 類的派生類

class Foo(object):
  pass
class Bar(Foo):
  pass
print(issubclass(Bar, Foo))  #結果為True

二、 反射

1 、什麽是反射

  反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了計算機科學領域關於應用反射性的研究。它首先被程序語言的設計領域所采用,並在Lisp和面向對象方面取得了成績。

2 、python面向對象中的反射:通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)

四個可以實現自省的函數:

hasattrgetattrsetattrdelattr

下列方法適用於類和對象(一切皆對象,類本身也是一個對象)

# 1、hasattr
# print(hasattr(People,‘country‘))  #True
# print(‘country‘ in People.__dict__) #不知道hasattr方法時,用的方法 # print(hasattr(obj,‘name‘)) #True # print(hasattr(obj,‘country‘)) #True # print(hasattr(obj,‘tell‘)) #True # 2、getattr # x=getattr(People,‘country1‘,None) #查找指定屬性,沒有此屬性(提前預防報錯寫None)顯示None,有就返回值 # print(x)
# f=getattr(obj,‘tell‘,None)#obj.tell # print(f == obj.tell) #True # f() #正常的調用函數 # obj.tell() # 3、setattr # People.x=111 # setattr(People,‘x‘,111) #添加x屬性,值為111 # print(People.x) # obj.age=18 # setattr(obj,"age",18) # 添加age屬性,值為18 # print(obj.__dict__) # 4、delattr # del People.country #原始的方法 # delattr(People,"country") # print(People.__dict__) # del obj.name # delattr(obj,"name") # print(obj.__dict__)

三、__str__

class People:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def __str__(self):
        # print(‘========>‘)
        return <名字:%s 年齡:%s 性別:%s> %(self.name,self.age,self.sex)

obj=People(duoduo,18,male)
print(obj) #print(obj.__str__())  在print時觸發__str__

四、 __del__

當對象在內存中被釋放時,自動觸發執行。

註:如果產生的對象僅僅只是python程序級別的(用戶級),那麽無需定義__del__,如果產生的對象的同時還會向操作系統發起系統調用,即一個對象有用戶級與內核級兩種資源

import time

class People:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def __del__(self): # 在對象被刪除的條件下,自動執行
        print(__del__)

obj=People(duoduo,18,male)

#del obj #obj.__del__()      #先刪除的情況下,直接執行__del__

time.sleep(5)    #可以更形象的看出在資源回收前執行__del__

典型的應用場景:

創建數據庫類,用該類實例化出數據庫鏈接對象,對象本身是存放於用戶空間內存中,而鏈接則是由操作系統管理的,存放於內核空間內存中

當程序結束時,python只會回收自己的內存空間,即用戶態內存,而操作系統的資源則沒有被回收,這就需要我們定制__del__,在對象被刪除前向操作系統發起關閉數據庫鏈接的系統調用,回收資源

這與文件處理是一個道理:

f=open(a.txt) #做了兩件事,在用戶空間拿到一個f變量,在操作系統內核空間打開一個文件
del f #只回收用戶空間的f,操作系統的文件還處於打開狀態
#所以我們應該在del f之前保證f.close()執行,即便是沒有del,程序執行完畢也會自動del清理資源,於是文件操作的正確用法應該是
f=open(a.txt)
讀寫...
f.close()
#很多情況下大家都容易忽略f.close,這就用到了with上下文管理

class MyOpen:          #自己寫個打開讀文件類,封裝內置的open
    def __init__(self,filepath,mode="r",encoding="utf-8"):
        self.filepath=filepath
        self.mode=mode
        self.encoding=encoding
        self.fobj=open(filepath,mode=mode,encoding=encoding)  #申請系統內存

    def __str__(self):
        msg="""
        filepath:%s
        mode:%s
        encoding:%s
        """ %(self.filepath,self.mode,self.encoding)
        return msg

    def __del__(self):
        self.fobj.close()

f=MyOpen(aaa.py,mode=r,encoding=utf-8)
# print(f.filepath,f.mode,f.encoding)
# print(f)

# print(f.fobj)
res=f.fobj.read()   #一樣可以讀
print(res)

五、exec

#例子 一
code="""                     
#global x     #shsh聲明x為全局變量
x=0
y=2
"""
global_dic={x:100000}
local_dic={}         #字符串中聲明全局就是全局,不聲明就是局部
exec(code,global_dic,local_dic)
#
# print(global_dic)
# print(local_dic)

#例子 二
# code="""
# x=1
# y=2
# def f1(self,a,b):
#     pass
# """
# local_dic={}
# exec(code,{},local_dic)
# print(local_dic)

六、元類

1、什麽是元類:

  類的類就是元類
#我們用class定義的類使用來產生我們自己的對象的
#內置元類type是用來專門產生class定義的類的

#一切皆為對象:
# Chinese=type(...)
 class Chinese:
     country="China"

     def __init__(self,name,age,sex):
         self.name=name
         self.age=age
         self.sex=sex

     def speak(self):
         print(%s speak Chinese %self.name)

# print(Chinese)
# p=Chinese(‘duoduo‘,18,‘male‘)
# print(type(p))     #最上層的類 type

# print(type(Chinese))

2、用內置的元類type,來實例化得到我們的類

#2、用內置的元類type,來實例化得到我們的類
class_name=Chinese
class_bases=(object,)
lass_body="""
country="China"
def __init__(self,name,age,sex):
     self.name=name
     self.age=age
     self.sex=sex
 def speak(self):
     print(‘%s speak Chinese‘ %self.name)
 """
class_dic={}
exec(class_body,{},class_dic)
 #類的三大要素
# print(class_name,class_bases,class_dic)

Chinese=type(class_name,class_bases,class_dic)
# print(Chinese)

p=Chinese(duoduo,18,male)
# print(p.name,p.age,p.sex)

3、 __call__

對象後面加括號,觸發執行。

註:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()

class Foo:
    def __init__(self):
        pass
    def __str__(self):
        return 123123
    def __del__(self):
        pass
    # 調用對象,則會自動觸發對象下的綁定方法__call__的執行,
    # 然後將對象本身當作第一個參數傳給self,將調用對象時括號內的值
    #傳給*args與**kwargs
    def __call__(self, *args, **kwargs):
        print(__call__,args,kwargs)

obj=Foo()
# print(obj)

obj(1,2,3,a=1,b=2,c=3) #

4、自定義元類

class Mymeta(type):
    # 來控制類Foo的創建
    def __init__(self,class_name,class_bases,class_dic): #self=Foo
        # print(class_name)
        # print(class_bases)
        # print(class_dic)
        if not class_name.istitle():     #加上判斷
            raise TypeError(類名的首字母必須大寫)

        if not class_dic.get(__doc__):
            raise TypeError(類中必須寫好文檔註釋)
             
    super(Mymeta,self).__init__(class_name,class_bases,class_dic)

    # 控制類Foo的調用過程,即控制實例化Foo的過程
    def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}
        # print(self)
        # print(args)
        # print(kwargs)

        #1 造一個空對象obj
        obj=object.__new__(self)

        #2、調用Foo.__init__,將obj連同調用Foo括號內的參數一同傳給__init__
        self.__init__(obj,*args,**kwargs)

        return obj

#Foo=Mymeta(‘Foo‘,(object,),class_dic)
class Foo(object,metaclass=Mymeta):
    """
    文檔註釋
    """
    x=1
    def __init__(self,y):
        self.Y=y

    def f1(self):
        print(from f1)

obj=Foo(1111) #Foo.__call__()

# print(obj)
# print(obj.y)
# print(obj.f1)
# print(obj.x)

5、單例模式

import settings   #調用配置文件的IP,PORT

class MySQL:
    __instance=None
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port

    @classmethod   #綁定方法
    def singleton(cls):
        if not cls.__instance:
            obj=cls(settings.IP, settings.PORT)  
            cls.__instance=obj
        return cls.__instance

obj1=MySQL(1.1.1.2,3306)
obj2=MySQL(1.1.1.3,3307)
obj3=MySQL(1.1.1.4,3308)

# obj4=MySQL(settings.IP,settings.PORT)
# print(obj4.ip,obj4.port)

obj4=MySQL.singleton()
obj5=MySQL.singleton()
obj6=MySQL.singleton()

print(obj4 is obj5 is obj6)    #Ture

python3全棧開發-內置函數補充,反射,元類,__str__,__del__,exec,type,__call__方法