黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

Python 私有屬性和名字重整、魔法屬性和方法、上下文管理器

系統(tǒng) 2305 0

修改、查看私有屬性、名字重整

如下,Test類(lèi)定義 一個(gè)私有屬性 __name? 實(shí)例化一個(gè)對(duì)象 a ,無(wú)法調(diào)用該屬性,

打印 a.__dict__( 可以檢查一個(gè)對(duì)象的所有屬性 )查看?,發(fā)現(xiàn)__name存在并且名字變?yōu)? _Test__name (無(wú)法調(diào)用的原因,名字被改變)

改變規(guī)則:私有屬性前添加類(lèi)名,再在類(lèi)名前添加一個(gè)下劃線(xiàn) ( 名字重整

Python 私有屬性和名字重整、魔法屬性和方法、上下文管理器_第1張圖片

我們驗(yàn)證一下,打印修改后的屬性,如下

?

這里有個(gè)疑問(wèn),既然無(wú)法直接打印,那我們?yōu)槭裁纯梢灾苯有薷模?

修改測(cè)試一下,打印輸出,此時(shí)__name 并不是私有屬性了,此時(shí)的 __name 只是添加了一個(gè)屬性,可以直接調(diào)用

這里就沒(méi)有什么私有公有之說(shuō)了,所謂的公有私有,是指類(lèi)中的屬性,實(shí)例對(duì)象無(wú)法直接調(diào)用

Python 私有屬性和名字重整、魔法屬性和方法、上下文管理器_第2張圖片 ? ? ? ? ? ? ?

另外補(bǔ)充一下 __dict__屬性,Test類(lèi)也是一個(gè)對(duì)象,查看其屬性:每個(gè)魔法屬性對(duì)應(yīng)值或函數(shù)

?

?

魔法屬性、方法

無(wú)論人或事物往往都有不按套路出牌的情況,Python的類(lèi)屬性也是如此。存在一些具有特殊含義的屬性

如上圖,對(duì)應(yīng)的魔法屬性:

?

1. __doc__ :表示類(lèi)的描述信息,help()方法也可以輸出類(lèi)的描述信息

            
              class Test():
    """
    This is a description of a class
    """
    pass


print(Test.__doc__)
print("*" * 15)
print(help(Test))
            
          

Python 私有屬性和名字重整、魔法屬性和方法、上下文管理器_第3張圖片

?

2. __module__? 和 __class__ :__module__表示當(dāng)前操作在哪個(gè)模塊,__class__表示當(dāng)前操作的對(duì)象的類(lèi)是什么

            
              # -*- coding:utf-8 -*-


# test.py
class Person(object):
    def __init__(self):
        self.name = 'laowang'
            
          
            
              

from test import Person


# main.py
obj = Person()
print(obj.__module__)  # 輸出創(chuàng)建該對(duì)象的對(duì)應(yīng)模塊  test
print(obj.__class__)  # 輸出創(chuàng)建該對(duì)象的對(duì)應(yīng)模塊中的類(lèi)    test.Person
            
          

?

3. __init__ :初始化方法(不建議稱(chēng)其為構(gòu)造方法,可以說(shuō)__init__ 和 __new__ 方法一起完成了構(gòu)造方法的功能),通過(guò)類(lèi)創(chuàng)建對(duì)象時(shí),自動(dòng)觸發(fā)執(zhí)行

            
              class Person:
    def __init__(self, name):
        self.name = name
        self.age = 18


obj = Person('laowang')  # 自動(dòng)執(zhí)行類(lèi)中的 __init__ 方法

            
          

?

4. __del__:當(dāng)對(duì)象在內(nèi)存中被釋放時(shí),自動(dòng)觸發(fā)執(zhí)行

注:此方法無(wú)需定義,因?yàn)閜ython是一門(mén)高級(jí)語(yǔ)言,程序員在使用時(shí),無(wú)需關(guān)系內(nèi)存的分配和釋放,因?yàn)榇斯ぷ鞫际墙唤oPython的解釋器來(lái)執(zhí)行,所以,__del__的調(diào)用是有解釋器在進(jìn)行垃圾回收時(shí)自動(dòng)觸發(fā)執(zhí)行的。

            
              class Foo:
    def __del__(self):
        pass
            
          

?

5. __call__:對(duì)象后面加括號(hào),觸發(fā)執(zhí)行? (用于裝飾器)

注:__init__方法的執(zhí)行是由創(chuàng)建對(duì)象觸發(fā)的,即 對(duì)象 = 類(lèi)名() ; 而對(duì)于__call__ 方法執(zhí)行是由對(duì)象后加括號(hào)觸發(fā)的,即

對(duì)象()? 類(lèi)()

            
              class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')


obj = Foo()  # 執(zhí)行 __init__
obj()  # 執(zhí)行 __call__
            
          

?

6. __dict__ :?類(lèi)或?qū)ο笾械乃袑傩? ? ? ? ?

類(lèi)的實(shí)例屬性屬于對(duì)象;類(lèi)中的類(lèi)屬性和方法等屬于類(lèi),即:

            
              class Province(object):
    country = 'China'

    def __init__(self, name, count):
        self.name = name
        self.count = count

    def func(self, *args, **kwargs):
        print('func')

# 獲取類(lèi)的屬性,即:類(lèi)屬性、方法、
print(Province.__dict__)
# 輸出:{'__dict__': 
              
                , '__module__': '__main__', 'country': 'China', '__doc__': None, '__weakref__': 
                
                  , 'func': 
                  
                    , '__init__': 
                    
                      }

obj1 = Province('山東', 10000)
print(obj1.__dict__)
# 獲取 對(duì)象obj1 的屬性
# 輸出:{'count': 10000, 'name': '山東'}

obj2 = Province('山西', 20000)
print(obj2.__dict__)
# 獲取 對(duì)象obj1 的屬性
# 輸出:{'count': 20000, 'name': '山西'}
                    
                  
                
              
            
          

?

7.?__str__:如果一個(gè)類(lèi)中定義了__str__方法,那么在打印 對(duì)象 時(shí),默認(rèn)輸出該方法的返回值

            
              class Foo:
    def __str__(self):
        return 'laowang'


obj = Foo()
print(obj)
# 輸出:laowang
            
          

?

8.?__getitem__、__setitem__、__delitem__ :用于索引操作,如字典。以上分別表示獲取、設(shè)置、刪除數(shù)據(jù)

            
              # -*- coding:utf-8 -*-

class Foo(object):

    def __getitem__(self, key):
        print('__getitem__', key)

    def __setitem__(self, key, value):
        print('__setitem__', key, value)

    def __delitem__(self, key):
        print('__delitem__', key)


obj = Foo()

result = obj['k1']      # 自動(dòng)觸發(fā)執(zhí)行 __getitem__
obj['k2'] = 'laowang'   # 自動(dòng)觸發(fā)執(zhí)行 __setitem__
del obj['k1']           # 自動(dòng)觸發(fā)執(zhí)行 __delitem__
            
          

9.?__getitem__、__setitem__、__delitem__ :該三個(gè)方法用于分片操作,如:列表

            
              # -*- coding:utf-8 -*-

class Foo(object):

    def __getslice__(self, i, j):
        print('__getslice__', i, j)

    def __setslice__(self, i, j, sequence):
        print('__setslice__', i, j)

    def __delslice__(self, i, j):
        print('__delslice__', i, j)

obj = Foo()

obj[-1:1]                   # 自動(dòng)觸發(fā)執(zhí)行 __getslice__
obj[0:1] = [11,22,33,44]    # 自動(dòng)觸發(fā)執(zhí)行 __setslice__
del obj[0:2]                # 自動(dòng)觸發(fā)執(zhí)行 __delslice__
            
          

?

?

With、上下文管理器

對(duì)于系統(tǒng)資源如文件、數(shù)據(jù)庫(kù)連接、socket 而言,應(yīng)用程序打開(kāi)這些資源并執(zhí)行完業(yè)務(wù)邏輯之后,必須做的一件事就是要關(guān)閉(斷開(kāi))該資源。

比如 Python 程序打開(kāi)一個(gè)文件,往文件中寫(xiě)內(nèi)容,寫(xiě)完之后,就要關(guān)閉該文件,否則會(huì)出現(xiàn)什么情況呢?極端情況下會(huì)出現(xiàn) "Too many open files" 的錯(cuò)誤,因?yàn)橄到y(tǒng)允許你打開(kāi)的最大文件數(shù)量是有限的。

同樣,對(duì)于數(shù)據(jù)庫(kù),如果連接數(shù)過(guò)多而沒(méi)有及時(shí)關(guān)閉的話(huà),就可能會(huì)出現(xiàn) "Can not connect to MySQL server Too many connections",因?yàn)閿?shù)據(jù)庫(kù)連接是一種非常昂貴的資源,不可能無(wú)限制的被創(chuàng)建。

普通版:

            
              def m1():
    f = open("output.txt", "w")
    f.write("python之禪")
    f.close()
            
          

這樣寫(xiě)有一個(gè)潛在的問(wèn)題,如果在調(diào)用 write 的過(guò)程中,出現(xiàn)了異常進(jìn)而導(dǎo)致后續(xù)代碼無(wú)法繼續(xù)執(zhí)行,close 方法無(wú)法被正常調(diào)用,因此資源就會(huì)一直被該程序占用者釋放。

?

進(jìn)階版:

            
              def m2():
    f = open("output.txt", "w")
    try:                      
        f.write("python之禪")
    except IOError:            # except 未捕獲到對(duì)應(yīng)異常,依然會(huì)崩
        print("oops error")
    finally:
        f.close()
            
          

改良版本的程序是對(duì)可能發(fā)生異常的代碼處進(jìn)行 try 捕獲,使用 try/finally 語(yǔ)句,該語(yǔ)句表示如果在 try 代碼塊中程序出現(xiàn)了異常,后續(xù)代碼就不再執(zhí)行,而直接跳轉(zhuǎn)到 except 代碼塊。而無(wú)論如何,finally 塊的代碼最終都會(huì)被執(zhí)行。因此,只要把 close 放在 finally 代碼中,文件就一定會(huì)關(guān)閉。

?

高級(jí)版:

            
              def m3():
    with open("output.txt", "r") as f:
        f.write("Python之禪")
            
          

一種更加簡(jiǎn)潔、優(yōu)雅的方式就是用 with 關(guān)鍵字。 open 方法的返回值賦值給變量 f,當(dāng)離開(kāi) with 代碼塊的時(shí)候,系統(tǒng)會(huì)自動(dòng)調(diào)用 f.close() 方法, with 的作用和使用 try/finally 語(yǔ)句是一樣的。那么它的實(shí)現(xiàn)原理是什么?在講 with 的原理前要涉及到另外一個(gè)概念,就是 上下文管理器(Context Manager)

?

上下文(context)

上下文在不同的地方表示不同的含義,要感性理解。context其實(shí)說(shuō)白了,和文章的上下文是一個(gè)意思,通俗一點(diǎn),理解為環(huán)境

?

上下文管理器

任何實(shí)現(xiàn)了 __enter__() 和 __exit__() 方法的對(duì)象都可稱(chēng)之為上下文管理器 ,上下文管理器對(duì)象可以使用 with 關(guān)鍵字。顯然,文件(file)對(duì)象也實(shí)現(xiàn)了上下文管理器。

那么文件對(duì)象是如何實(shí)現(xiàn)這兩個(gè)方法的呢?我們可以模擬實(shí)現(xiàn)一個(gè)自己的文件類(lèi),讓該類(lèi)實(shí)現(xiàn) __enter__() __exit__() 方法。

            
              class File():

    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        print("entering")
        self.f = open(self.filename, self.mode)
        return self.f

    def __exit__(self, *args):
        print("will exit")
        self.f.close()
            
          

__enter__() 方法返回資源對(duì)象,這里就是你將要打開(kāi)的那個(gè)文件對(duì)象,__exit__() 方法處理一些清除工作。

因?yàn)?File 類(lèi)實(shí)現(xiàn)了上下文管理器,現(xiàn)在就可以使用 with 語(yǔ)句了。

            
              with File('out.txt', 'w') as f: 
# 實(shí)例化File對(duì)象,執(zhí)行__init__方法,filename屬性對(duì)應(yīng)out.txt,w對(duì)應(yīng)mode屬性
# with判斷其是否是一個(gè)上下文管理器(實(shí)現(xiàn)對(duì)應(yīng)的方法),然后自動(dòng)調(diào)用 __enter__()方法 
# __enter__()方法返回值是什么,對(duì)應(yīng)的 f 就是什么,而當(dāng)結(jié)束或者出現(xiàn)異常時(shí),會(huì)自動(dòng)調(diào)用 __exit__()
# 方法
    print("writing")
    f.write('hello, python')
            
          

這樣,你就無(wú)需顯示地調(diào)用 close 方法了,由系統(tǒng)自動(dòng)去調(diào)用,哪怕中間遇到異常 close 方法也會(huì)被調(diào)用。

?

實(shí)現(xiàn)上下文管理器的另外方式(了解)

Python 還提供了一個(gè) contextmanager 的裝飾器,更進(jìn)一步簡(jiǎn)化了上下文管理器的實(shí)現(xiàn)方式。通過(guò) yield 將函數(shù)分割成兩部分,yield 之前的語(yǔ)句在 __enter__ 方法中執(zhí)行,yield 之后的語(yǔ)句在 __exit__ 方法中執(zhí)行。緊跟在 yield 后面的值是函數(shù)的返回值。

            
              from contextlib import contextmanager

@contextmanager
def my_open(path, mode):
    f = open(path, mode)
    yield f
    f.close()
調(diào)用

with my_open('out.txt', 'w') as f:
    f.write("hello , the simplest context manager")
            
          

?

?

總結(jié)

Python 提供了? with 語(yǔ)法用于簡(jiǎn)化資源操作的后續(xù)清除操作,是 try/finally 的替代方法,實(shí)現(xiàn)原理建立在上下文管理器之上。 此外,Python 還提供了一個(gè) contextmanager 裝飾器,更進(jìn)一步簡(jiǎn)化上下管理器的實(shí)現(xiàn)方式。

?

?

?

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論