前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python-静态方法staticmethod、类方法classmethod、属性方法property

python-静态方法staticmethod、类方法classmethod、属性方法property

作者头像
狼啸风云
修改2022-09-03 19:48:48
2.1K0
修改2022-09-03 19:48:48
举报
文章被收录于专栏:计算机视觉理论及其实现

Python的方法主要有3个,即静态方法(staticmethod),类方法(classmethod)和实例方法:

代码语言:javascript
复制
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)

类的普通方法

代码语言:javascript
复制
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()
  • 静态类方法
代码语言:javascript
复制
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中的方法,可以直接使用的工具包,跟类没关系。


代码语言:javascript
复制
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()
  • 报错信息

如果换成

代码语言:javascript
复制
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广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。(摘自廖雪峰的博客)

代码语言:javascript
复制
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()
  • 报错:
  • 方法不能正常调用。如果要调用,如下:
代码语言:javascript
复制
cat.intro
  • 是这样的话,方法就没办法单独传入参数。如果要传入参数,如下:
代码语言:javascript
复制
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):
        pass
cat = Animal('cat')
cat.intro
  • cat.intro还有其他操作getter deleter等等。

一:staticmethod

代码如下:

代码语言:javascript
复制
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.instance

a = 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

和方法一类似,代码:

代码语言:javascript
复制
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.instance

a = Singleton.get_instance()
b = Singleton.get_instance()
print('a id=', id(a))
print('b id=', id(b))

该方法的要点是在__init__抛出异常,禁止通过类来实例化,只能通过静态get_instance函数来获取实例;因为不能通过类来实例化,所以静态get_instance函数中可以通过父类object.__new__来实例化。

三:类属性方法

和方法一类似, 代码:

代码语言:javascript
复制
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.instance

a = Singleton.get_instance()
b = Singleton.get_instance()
print(id(a))
print(id(b))

该方法的要点是在__init__抛出异常,禁止通过类来实例化,只能通过静态get_instance函数来获取实例;因为不能通过类来实例化,所以静态get_instance函数中可以通过父类object.__new__来实例化。

四:__new__

常见的方法, 代码如下:

代码语言:javascript
复制
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.instance


a = Singleton()
b = Singleton()
print(id(a))
print(id(b))

五:装饰器

代码如下:

代码语言:javascript
复制
def Singleton(cls):
    instances = {}

    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance


@Singleton
class MyClass:
    pass

a = MyClass()
b = MyClass()
c = MyClass()

print(id(a))
print(id(b))
print(id(c))

六:元类

python2版:

代码语言:javascript
复制
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.instance


class MyClass(object):
    __metaclass__ = Singleton


a = MyClass()
b = MyClass()
c = MyClass()
print(id(a))
print(id(b))
print(id(c))
print(a is b)
print(a is c)

或者:

代码语言:javascript
复制
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._instance


class Foo(object):
    __metaclass__ = Singleton

x = Foo()
y = Foo()
print(id(x))
print(id(y))

python3版:

代码语言:javascript
复制
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.instance


class Foo(metaclass=Singleton):
    pass

x = Foo()
y = Foo()
print(id(x))
print(id(y))

七:名字覆盖

代码如下:

代码语言:javascript
复制
class Singleton(object):
    def foo(self):
        print('foo')

    def __call__(self):
        return self


Singleton = Singleton()

Singleton.foo()

a = Singleton()
b = Singleton()
print(id(a))
print(id(b))
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:staticmethod
  • 二:classmethod
  • 三:类属性方法
  • 四:__new__
  • 五:装饰器
  • 六:元类
  • 七:名字覆盖
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档