python类的类方法,静态方法,属性方法,普通方法的实现及区别

2020-02-18  本文已影响0人  hugoren

先看例子

class T:

    def test_1(self):
        print("test_1")

    @property
    def test_2(self):
        print("property")

    @classmethod
    def test_3(cls):
        print("cls")

    @staticmethod
    def test_4():
        print("static")

t = T()
t.test_1()
t.test_2
t.test_3()
T.test_3()
t.test_4()
T.test_4()

概念上的区别

实例方法

定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法);

调用:只能由实例对象调用。

类方法

定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);

调用:实例对象和类对象都可以调用。

静态方法

定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;

调用:实例对象和类对象都可以调用。

什么场景下使用

底层的实例

property的实现

class Property:

    # 装饰器类的语法和装饰器方法类似,
    # @property等价于roperty(...)
    # 入参体现在初始化方法中
    def __init__(self, func):
        self.__name__ = func.__name__
        self.getF = func
        self.setF = None
        pass

    def setter(self, func):
        self.setF = func
        return self

    def __set__(self, instance, value):
        self.setF(instance, value)
        pass

    def __get__(self, instance, owner):
        return self.getF(instance)

class A(object):
    
    # 利用roperty像property一样定义属性
    # 这里等价于name = roperty(name)
    # 利用装饰器语法,name被赋值为roperty的实例
    @roperty
    def name(self):
        print('get name1')
        return self.__name
        
    # 由于name被赋值为roperty的实例
    # 为了演示上的区分,方法名为name1,实际开发中用name即可
    # 以下等价于name1 = name.setter(name1)
    @name.setter
    def name1(self, n):
        print('set name')
        self.__name = n

a = A()

# 值得注意的是,经过装饰器语法后A.name已经是roperty对象(这里roperty对象既是一个装饰器又是一个描述器)
# 根据描述器的特性,a.name赋值会触发描述器的__set__方法,继而调用name属性定义的set方法
a.name = 'name1111'

# 根据描述器的特性,a.name读取会触发描述器的__get__方法,继而调用name属性定义的get方法
print(a.name)

classmethod 与staticmethod 的实现

class classmethod1(object):

    def __init__(self, func):
        self.sf = func

    def __get__(self, instance, owner):
        return lambda *args, **kwargs: self.sf(owner, *args, **kwargs)

class staticmethod1(object):

    def __init__(self, func):
        self.sf = func

    def __get__(self, instance, owner):
        return lambda *args, **kwargs: self.sf(*args, **kwargs)

class T(object):

    def name(self):
        print('instance.name')

    @classmethod1
    def className(cls):
        print('{}.name'.format(cls))

    @staticmethod1
    def staticName(ipt):
        print('{}.name'.format(ipt))

上一篇下一篇

猜你喜欢

热点阅读