標籤:檢查 工具包 圖片 index attrs png return set 舉例
Python的方法主要有3個,即靜態方法(staticmethod),類方法(classmethod)和執行個體方法
| 12345678910111213141516 |
def foo(x): print "executing foo(%s)"%(x) class A(object): def foo(self,x): print "executing foo(%s,%s)"%(self,x) @classmethod def class_foo(cls,x): print "executing class_foo(%s,%s)"%(cls,x) @staticmethod def static_foo(x): print "executing static_foo(%s)"%x a=A() |
這個self和cls是對類或者執行個體的綁定,對於一般的函數來說我們可以這麼調用foo(x),這個函數就是最常用的,它的工作跟任何東西(類,執行個體)無關.對於執行個體方法,我們知道在類裡每次定義方法的時候都需要綁定這個執行個體,就是foo(self, x),為什麼要這麼做呢?因為執行個體方法的調用離不開執行個體,我們需要把執行個體自己傳給函數,調用的時候是這樣的a.foo(x)(其實是foo(a, x)).類方法一樣,只不過它傳遞的是類而不是執行個體,A.class_foo(x).注意這裡的self和cls可以替換別的參數,但是python的約定是這倆,還是不要改的好.
對於靜態方法其實和普通的方法一樣,不需要對誰進行綁定,唯一的區別是調用的時候需要使用a.static_foo(x)或者A.static_foo(x)來調用.
| \ |
執行個體方法 |
類方法 |
靜態方法 |
| a = A() |
a.foo(x) |
a.class_foo(x) |
a.static_foo(x) |
| A |
不可用 |
A.class_foo(x) |
A.static_foo(x)
|
類的普通方法
class Animal(object): def __init__(self,name): self.name = name def intro(self): print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
class Animal(object): def __init__(self,name): self.name = name @staticmethod def intro(self): print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
- 加上裝飾器後運行會報錯,原因是方法變為一個普通函數,脫離的與類的關係,不能引用建構函式中的變數了。
使用情境舉例:python內建方法os中的方法,可以直接使用的工具包,跟類沒關係。
class Animal(object): def __init__(self,name): self.name = name @classmethod def intro(self): print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
如果換成
class Animal(object): name = ‘cat‘ def __init__(self,name): self.name = name @classmethod def intro(self): print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
結論:類方法只能調用類變數,不能調用執行個體變數
屬性方法@property 把一個方法變為(偽裝成)類屬性。因為類屬性的實質是一個類變數,使用者可以調用變數就可以修改變數。某些特定情境要限制使用者行為,就用到靜態方法。
@property廣泛應用在類的定義中,可以讓調用者寫出簡短的代碼,同時保證對參數進行必要的檢查,這樣,程式運行時就減少了出錯的可能性。(摘自廖雪峰的部落格)
class Animal(object): def __init__(self,name): self.name = name @property def intro(self,food): print(‘there is a %s eating %s‘%(self.name,food))cat = Animal(‘cat‘)cat.intro()
cat.intro
- 是這樣的話,方法就沒辦法單獨傳入參數。如果要傳入參數,如下:
class Animal(object): def __init__(self,name): self.name = name @property def intro(self): print(‘there is a %s eating %s‘%(self.name,food)) @intro.setter def intro(self,food): passcat = Animal(‘cat‘)cat.intro
- cat.intro還有其他動作getter deleter等等。
一:staticmethod代碼如下:
class Singleton(object): instance = None def __init__(self): raise SyntaxError(‘can not instance, please use get_instance‘) @staticmethod def get_instance(): if Singleton.instance is None: Singleton.instance = object.__new__(Singleton) return Singleton.instancea = Singleton.get_instance()b = Singleton.get_instance()print(‘a id=‘, id(a))print(‘b id=‘, id(b))
該方法的要點是在__init__拋出異常,禁止通過類來執行個體化,只能通過靜態get_instance函數來擷取執行個體;因為不能通過類來執行個體化,所以靜態get_instance函數中可以通過父類object.__new__來執行個體化。 二:classmethod和方法一類似,代碼:
class Singleton(object): instance = None def __init__(self): raise SyntaxError(‘can not instance, please use get_instance‘) @classmethod def get_instance(cls): if Singleton.instance is None: Singleton.instance = object.__new__(Singleton) return Singleton.instancea = Singleton.get_instance()b = Singleton.get_instance()print(‘a id=‘, id(a))print(‘b id=‘, id(b))
該方法的要點是在__init__拋出異常,禁止通過類來執行個體化,只能通過靜態get_instance函數來擷取執行個體;因為不能通過類來執行個體化,所以靜態get_instance函數中可以通過父類object.__new__來執行個體化。 三:類屬性方法和方法一類似, 代碼:
class Singleton(object): instance = None def __init__(self): raise SyntaxError(‘can not instance, please use get_instance‘) def get_instance(): if Singleton.instance is None: Singleton.instance = object.__new__(Singleton) return Singleton.instancea = Singleton.get_instance()b = Singleton.get_instance()print(id(a))print(id(b))
該方法的要點是在__init__拋出異常,禁止通過類來執行個體化,只能通過靜態get_instance函數來擷取執行個體;因為不能通過類來執行個體化,所以靜態get_instance函數中可以通過父類object.__new__來執行個體化。 四:__new__
常見的方法, 代碼如下:
class Singleton(object): instance = None def __new__(cls, *args, **kw): if not cls.instance: # cls.instance = object.__new__(cls, *args) cls.instance = super(Singleton, cls).__new__(cls, *args, **kw) return cls.instancea = Singleton()b = Singleton()print(id(a))print(id(b))
五:裝飾器
代碼如下:
def Singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance@Singletonclass MyClass: passa = MyClass()b = MyClass()c = MyClass()print(id(a))print(id(b))print(id(c))
六:元類python2版:
class Singleton(type): def __init__(cls, name, bases, dct): super(Singleton, cls).__init__(name, bases, dct) cls.instance = None def __call__(cls, *args): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args) return cls.instanceclass MyClass(object): __metaclass__ = Singletona = MyClass()b = MyClass()c = MyClass()print(id(a))print(id(b))print(id(c))print(a is b)print(a is c)
或者:
class Singleton(type): def __new__(cls, name, bases, attrs): attrs["_instance"] = None return super(Singleton, cls).__new__(cls, name, bases, attrs) def __call__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super(Singleton, cls).__call__(*args, **kwargs) return cls._instanceclass Foo(object): __metaclass__ = Singletonx = Foo()y = Foo()print(id(x))print(id(y))
python3版:
class Singleton(type): def __new__(cls, name, bases, attrs): attrs[‘instance‘] = None return super(Singleton, cls).__new__(cls, name, bases, attrs) def __call__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args, **kwargs) return cls.instanceclass Foo(metaclass=Singleton): passx = Foo()y = Foo()print(id(x))print(id(y))
七:名字覆蓋代碼如下:
class Singleton(object): def foo(self): print(‘foo‘) def __call__(self): return selfSingleton = Singleton()Singleton.foo()a = Singleton()b = Singleton()print(id(a))print(id(b))
python-靜態方法staticmethod、類方法classmethod、屬性方法property