python中的特殊變量


  • 類似__xx,以雙下划線開頭的實例變量名,是一個私有變量(private),只有內部可以訪問,外部不能訪問;
  • 類似__xx__,以雙下划線開頭,並且以雙下划線結尾的,是特殊變量,特殊變量是可以直接訪問的,它不是private變量,下面會介紹Python中的常見特殊變量;
  • 類似_x,以單下划線開頭的實例變量名,這樣的變量外部是可以訪問的,但是,按照約定俗成的規定,當你看到這樣的變量時,意思就是,“雖然我可以被訪問,但是請把我視為私有變量,不要隨意訪問”。

特殊變量

#__name__

  • 如果直接執行某個.py文件的時候,這個文件里面的__name__就是__main__,如果不是直接執行,而是被另外一個.py文件import的時候,這個文件里面的__name__是這個py的文件名。
  • 使用這個__name__可以對程序進行調試,如果說當程序之間互相之間調用,比較復雜的關系的時候,使用if __name__ == '__main__':將執行的代碼放在里面,在執行其他的程序的時候,測試的程序本身不會運行,而這個程序有問題的時候,可以執行這個文件,那么if __name__ == '__main__':里面的代碼就執行了。

 

#__doc__

獲取模塊注釋

 

#__file__

當前執行文件的路徑

 

#__cached__

對應pycache文件的位置

 

#__name__

執行當前文件的時候,等於__main__;否則不等於;一般在主文件里寫

 

#__package__

模塊所在package

 

#__all__

python模塊中的__all__,可用於模塊導入時限制,如:

from module import *

此時被導入模塊若定義了__all__屬性,則只有__all__內指定的屬性、方法、類可被導入。

若沒定義,則導入模塊內的所有公有屬性,方法和類 。

# 在別的模塊中,導入該模塊時,只能導入__all__中的變量,方法和類
__all__ = ('A', 'func')  
class A():
    def __init__(self, name, age):
        self.name = name
        self.age = age

class B():
    def __init__(self, name, id):
        self.name = name
        self.id = id

def func():
    print('func() is called!')

def func1():
    print('func1() is called!')

 

#test.py中定義了__all__屬性,只能導入__all__中定義的屬性,方法和類
from test import *  
a=A('python','24')  
print(a.name,a.age)  
func()  
#func1() #NameError: name 'func1' is not defined  
#b=B('python',123456) #NameError: name 'B' is not defined  

  

 

#__slots__

Python允許在定義class的時候,定義一個特殊的__slots__變量,來限制該class實例能添加的屬性范圍

class P(object):
    __slots__ = ("name", "age")
    pass

 

#__init__()

構造函數,創建實例的時候,可以調用__init__方法做一些初始化的工作,如果子類重寫了__init__,實例化子類時,則只會調用子類的__init__,此時如果想使用父類的__init__,可以使用super函數,如下:

class P(object):
    def __init__(self, name, score):
        self.name = name
        self.score = name


class C(P):
    def __init__(self, name, score, age):
        super(C, self).__init__(name, score)
        self.age = age 

 

#__new__()

注意:__init__是實例創建之后調用的第一個方法,而__new__更像構造函數,它在__init__之前被調用。

另外,__new__方法是一個靜態方法,第一參數是cls,__new__方法必須返回創建出來的實例。

 

例如,用__new__實現單例模式:

class Singleton(object):
    def __new__(cls):
        # 關鍵在於這,每一次實例化的時候,我們都只會返回這同一個instance對象
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance
 
obj1 = Singleton()
obj2 = Singleton()
 
obj1.attr1 = 'value1'
print(obj1.attr1, obj2.attr1)
print(obj1 is obj2)

 

#__del__()

析構函數:__del__()    釋放對象是自動調用

 

#__str__()

在調用print打印對象時自動調用,是給用戶用的,是一個描述對象的方法。


#__repr__()

是給機器用的,在Python解釋器里面直接敲對象名在回車后調用的方法。(用於調試)

# test.py
class P(object):
    def __str__(self):
        return "__str__ called"

    def __repr__(self):
        return "__repr__ called"

p = P()

可以看下__str__和__repr__的區別:

>>> from test import p
>>> p
__repr__ called
>>> print p
__str__ called

  

 

#__enter__

#__exit__

這兩個方法是用於支持with語句的上下文管理器。

例如讓文件句柄支持with語法的實現:

class File(object):
    def __init__(self, file_name, method):
        self.file_obj = open(file_name, method)
    def __enter__(self):
        return self.file_obj
    def __exit__(self, type, value, traceback):
        self.file_obj.close()

with File('demo.txt', 'w') as opened_file:
    opened_file.write('Hola!')

 

#__iter__

next

如果一個類想被用於for ... in循環,類似list或tuple那樣,就必須實現一個__iter__()方法,該方法返回一個迭代對象,然后,Python的for循環就會不斷調用該迭代對象的next()方法拿到循環的下一個值,直到遇到StopIteration錯誤時退出循環。

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化兩個計數器a,b

    def __iter__(self):
        return self # 實例本身就是迭代對象,故返回自己

    def next(self):
        self.a, self.b = self.b, self.a + self.b # 計算下一個值
        if self.a > 100000: # 退出循環的條件
            raise StopIteration();
        return self.a # 返回下一個值

  

#__call__

實例可以像函數一樣調用。

class Student(object):

    def __init__(self):
        self.name = "Michael"

    def __call__(self):
        print('__call__ called')


s = Student()
s()

  

#__getitem__

#__setitem__

#__delitem__

支持下標(或切片)操作的函數

class Fib(object):
    def __getitem__(self, n): 
        if isinstance(n, int):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b 
            return a

        if isinstance(n, slice):
            start = n.start
            stop = n.stop
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b 
            return L

fib = Fib()
print(fib[10])
print(fib[0:10])

  

#__getattr__

#__getattribute__

#__setattr__

#__delattr__

支持點操作(即 "對象.屬性" 訪問方式),

 

當訪問不存在的屬性時,才會使用__getattr__  方法。

class Student(object):

    def __init__(self):
        self.name = "Michael"

    def __getattr__(self, attr):
        print '__getattr__ called'
        if attr=='score':
            return 99
        elif attr=='name':
            return "Tom"


s = Student()
print(s.score)       # 99
print(s.name)        # Michael

 

Python的字典支持下標操作,但不支持 "." 操作,如果想讓其支持,如下實現:

class Storage(dict):
    __slots__ = ()
    """
    A Storage object is like a dictionary except `obj.foo` can be used
    in addition to `obj['foo']`.

        >>> o = Storage(a=1)
        >>> o.a
        >>> o['a']
        >>> o.a = 2
        >>> o['a']
        >>> del o.a
        >>> o.a
        Traceback (most recent call last):
            ...
        AttributeError: 'a'
        >>> 'b' in o
        False

    """

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError, k:
            raise AttributeError(k)

    def __setattr__(self, key, value):
        self[key] = value

    def __delattr__(self, key):
        try:
            del self[key]
        except KeyError, k:
            raise AttributeError(k)
   
    def __repr__(self):
        return '<Storage ' + dict.__repr__(self) + '>'

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM