裝飾一個類及內部方法

經過裝飾器函數修改一個類屬性python

class MyClass:ide

    NAME = 'My CLASS HAHAHA'函數

    def __init__(self):測試

        passspa

print(MyClass.__dict__['NAME'])orm

My CLASS HAHAHA對象

等價於:get

def setname(name):it

    def warpper(cls):   io

        cls.NAME = name

        return cls

    return warpper

@setname('MY CLASS enen')  #

class MyClass:

    pass

print(MyClass.__dict__['NAME'])

MY CLASS enen

例2:

class MyClass:

    def foo(self):

        print('foo')

    def bar():

        print('bar')

a = MyClass()

a.bar()

報錯以下:

  File "E:\python_project\class_test.py", line 12, in <module>

    a.bar()

TypeError: bar() takes 0 positional arguments but 1 was given

提示最少須要給予一個參數才能夠

這麼寫的意思是,函數是普通函數,可是實例化以後是沒法使用

這樣是不符合規定的

改進:

使用裝飾器,第一個裝飾器使用類方法

@classmethod

class MyClass:

    xxx = 'hahaha'

    def foo(self):

        print('foo')

    def bar():

        print('bar')

    @classmethod

    def clsmtd(cls):

        print('{}.xxx = {}'.format(cls.__name__,cls.xxx))

a = MyClass()

a.foo()

MyClass.bar()

print(MyClass.__dict__)

foo

bar

{'xxx': 'hahaha', 'bar': <function MyClass.bar at 0x0000000000DD0488>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None, 'foo': <function MyClass.foo at 0x0000000000DD0400>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__module__': '__main__', 'clsmtd': <classmethod object at 0x0000000000DD70F0>}

a.clsmtd()

MyClass.xxx = hahaha

靜態方法使用

staticmethod

class MyClass:

    def foo(slef):

        return('foo')

    def bar():

        return('bar')

    @staticmethod

    def staticmtd():

        return('static')

a = MyClass()

print(MyClass.staticmtd())

print(a.staticmtd())

static

static

是類的方法便是全部對象的方法

py中的靜態方法,表示最通常的函數放在靜態方法中,可是受其管轄

而後測試bar方法是否可用

    @staticmethod

    def bar():

        return('bar')

a = MyClass()

print(a.bar())

bar

類方法

class Person:

    def haha():

        print('haha')

Person.haha()

haha

因爲沒有跟self,沒有完成實例的綁定,因此不能完成實例對象的綁定,因此不能用

Person().haha()

TypeError: haha() takes 0 positional arguments but 1 was given

Person().haha()

語法是對的,可是禁止這麼調用

@classmethod

class Person:

    HEIGHT = 16

    @classmethod

    def class_method(cls):

        print('class = {0.__name__} ({0})'.format(cls))

        cls.HEIGHT = 17

Person.class_method()

print(Person.HEIGHT)

for i in Person.__dict__.items():

    print(i)

返回以下:

class = Person (<class '__main__.Person'>)

17

('class_method', <classmethod object at 0x0000000000DA1278>)

('__weakref__', <attribute '__weakref__' of 'Person' objects>)

('__doc__', None)

('HEIGHT', 17)

('__module__', '__main__')

('__dict__', <attribute '__dict__' of 'Person' objects>)

在類定義中,使用@classmethod裝飾器修飾方法

至少有一個參數,並且第一個參數留給了cls,cls表示調用即類對象自身

cls表示標識符,能夠是任意名稱,可是爲了易讀性

類方法是能夠直接調用,而實例的方法要求實例必須存在,可是類存在的時候實例可能不存在

只要類方法定義過了,類對象就產生了,那麼找屬性便可找到

調用方法總結

代碼以下:

class Person:

    def no():

        print('no')

    def method(self):

        print('{} method'.format(self))

    @classmethod

    def class_method(cls):

        print('class = {0.__name__} ({0})'.format(cls))

        cls.HEIGHT = 170

    @staticmethod

    def static_method():

        print(Person.HETGHT)

方法調用

類的調用

print(Person.class_method())

class = Person (<class '__main__.Person'>)

print(Person.static_method())

不能調用

print(tom.method())

<__main__.Person object at 0x0000000000A97160> method

print(tom.class_method())

class = Person (<class '__main__.Person'>)

print(tom.static_method())

不能夠,沒有傳遞對象

除了普通方法均可以調用,可是普通方法都須要對象的實例做爲第一參數

實例能夠調用全部類中定義的方法,類和靜態方法

訪問控制

訪問控制主要爲了保護封裝不被破壞,可是python對外是可見的

私有屬性

屬性名前加入兩個下劃線表示當前方法不被破壞

class Person:

    age = 3

    height = 170

    def __init__(self,name,age=18):

        self.name = name

        self.age = age

    def growup(self,incr=1):

        if 0 < incr < 150:

            self.__age + incr

tom = Person('tom')

tom.age = 200

class Person:

    age = 3

    height = 170

    def __init__(self,name,age=18):

        self.name = name

        self.age = age

    def growup(self,incr=1):

        if 0 < incr < 150:

            self.__age + incr

    def getage(self):

        return self.__age

print(Person('tom').getage)

<bound method Person.getage of <__main__.Person object at 0x0000000000827208>>

class Person:

    def __init__(self,name,age=18):

        self.name = name

        self.__age = age

    def growup(self,incr=1):

        if 0 < incr < 150:

            self.__age += incr

    # 獲取內部屬性

    def getage(self):

        return self.__age

tom = Person('tom')

tom.growup(10)

print(tom.getage())

28

修改tom._Person__age

print(tom.getage())

tom._Person__age = 200

print(tom.getage())

200

查看tom.__dict__

print(tom.__dict__)

{'_Person__age': 200, 'name': 'tom'}

獲得的字典中,實際上是新加了一個key,而並不是被覆蓋

因此py的外界是能夠修改的隱藏方法的

新增長key:

tom._Person__ages = 200

print(tom.getage())

print(tom.__dict__)

{'name': 'tom', '_Person__age': 20, '_Person__ages': 200}

私有變量的本質

使用__變量名 時,會將其更名,轉爲_類名+前綴,因此原來名字訪問不到了

知道了這個名稱則能夠直接修改

print(a.__dict__)

{'name': 'tom', '_Person__age': 19}

保護變量

在變量前加一個下劃線,共同的約定,表示提醒你這個是一個內部私有的

而解釋器認爲私有的是私有變量

相關文章
相關標籤/搜索