装饰一个类及内部方法

简介:

通过装饰器函数修改一个类属性

class MyClass:

    NAME = 'My CLASS HAHAHA'

    def __init__(self):

        pass

print(MyClass.__dict__['NAME'])

My CLASS HAHAHA

等价于:

def setname(name):

    def warpper(cls):   

        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}

保护变量

在变量前加一个下划线,共同的约定,表示提醒你这个是一个内部私有的

而解释器认为私有的是私有变量



本文转自zuzhou 51CTO博客,原文链接:http://blog.51cto.com/yijiu/1981565


相关文章
|
1月前
|
存储 安全 C++
如何优雅地在C++库中实现实例化设计(二)
如何优雅地在C++库中实现实例化设计
14 0
|
6天前
|
Java
Java接口中可以定义哪些方法?
【4月更文挑战第13天】
7 0
Java接口中可以定义哪些方法?
|
1月前
|
存储 设计模式 缓存
如何优雅地在C++库中实现实例化设计(一)
如何优雅地在C++库中实现实例化设计
20 0
|
1月前
深入类的方法
深入类的方法
8 0
|
7月前
2.【类的组合(在一个类中定义一个类)】
2.【类的组合(在一个类中定义一个类)】
16 0
|
9月前
|
Python
python装饰器中的4种类型(函数装饰函数、函数装饰类、类装饰函数、类装饰类)
python装饰器中的4种类型(函数装饰函数、函数装饰类、类装饰函数、类装饰类)
88 0
|
JavaScript
JS面向对象之从工厂方式到构造函数
工厂方式 工厂方式其实就是函数封装,将多个对象相同部分封装成一个函数(功能) 将上面的代码封装成如下:
63 0
JS面向对象之从工厂方式到构造函数
|
Java
Java面向对象——类定义及使用、方法的定义及使用
Java面向对象——类定义及使用、方法的定义及使用
174 0
【自然框架】 页面里的父类——把共用的东东都交给父类,让子类专注于其他。
【类图】【命名空间】——————————————————【文件截图】   可能您会问,不就是弄个父类吗,怎么又是这么复杂呢?这个嘛,听我慢慢道来。 (类图里面Tree、Main1、DataDelete1、DataForm1、DataList1不是父类,而是共用页面)       这个是依据自然框架的特点来设置的,目的就是把共用的代码都放到父类里面,减轻子类的代码量。
870 0

热门文章

最新文章