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

摘要:
classAnimal:def__init__:self。名称=name@classmethoddefintro:printcat=动画。intro()如果错误消息更改为classAnimal:name='cat'def__init__:self。名称=name@classmethoddefintro:printcat=动画。intro()工作正常。静态方法用于限制某些场景中的用户行为。@Property在类的定义中被广泛使用。它允许调用者编写短代码,并确保根据需要检查参数。这样,程序运行时出错的可能性就降低了。如果要传入参数,如下所示:classAnimal:def__init__:self。名称=name@propertydefintro : print@intro.setterdefintro:passcat=动画。内向型。intro和其他操作,如getterdelete。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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-静态方法staticmethod、类方法classmethod、属性方法property第1张

使用场景举例: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()
  • 报错信息 

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

如果换成

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()
  • 报错:python-静态方法staticmethod、类方法classmethod、属性方法property第3张
  • 方法不能正常调用。如果要调用,如下:
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):
        pass
cat = 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.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

和方法一类似,代码:
 
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__来实例化。
 

三:类属性方法

和方法一类似, 代码:
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__

常见的方法, 代码如下:

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))

五:装饰器

代码如下:

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版:
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)

或者:
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版:
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))
 

七:名字覆盖

代码如下:
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))

免责声明:文章转载自《python-静态方法staticmethod、类方法classmethod、属性方法property》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux-PAM认证模块JavaScript 流程控制-循环下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Delphi线程基础知识

参考http://blog.chinaunix.net/uid-10535208-id-2949323.html 一、概述 Delphi提供了好几种对象以方便进行多线程编程。多线程应用程序有以下几方面的功能: 1.避免性能瓶颈:单线程应用程序在进行比较慢的操作如磁盘读写的时候,CPU必须停下来等待,直到该操作执行完毕。而多线程应用程序在进行比较慢的操作如磁...

Python基础语法三组合数据类型

一、列表(Lists)         列表属于Python中的序列类型,它是任意对象的有序集合,通过 “ 位置 ”或者 “ 索引 ” 访问其中的元素,它具有可变对象、可变长度、异构和任意嵌套的特点。         列表里第一个元素的为值或者索引是从 “ 0 ” 开始,第二个元素则是 “ 1 ”,一次类推。         列表的元素放置在方括号...

Python微信库:itchat

在论坛上看到了用Python登录微信并实现自动签到,才了解到一个新的Python库: itchat 库文档说明链接在这: itchat 我存个档在我网站(主要是我打开很慢),以便以后阅读。 0x01 Start 最简单的回复 通过如下代码,可以完成回复所有文本信息(包括群聊)。 import itchat from itchat.content impor...

基础面试题

1. 为什什么学习Python? Life is short, You need Python 2. 通过什什么途径学习的Python? pass 3. Python和Java、PHP、C、C#、C++等其他语⾔言的对比? pass 4. 简述解释型和编译型编程语言? 将由高级语言编写的程序文件转换为可执行文件(二进制的)有两种方式,编译和解释,编译是在...

操作系统知识总结

操作系统 面向进程和线程学习操作系统。 目录 Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 进程线程模型 进程间通信 同步互斥机制 存储管理 网络I/O模型 内容 进程线程模型 线程和进程的概念已经在操作系统书中被翻来覆去讲了很多遍。很多概念虽然都是套话,但没能理解透其中深意会导致很多内容...

Python引用模块和查找模块路径

模块间相互独立相互引用是任何一种编程语言的基础能力。对于“模块”这个词在各种编程语言中或许是不同的,但我们可以简单认为一个程序文件是一个模块,文件里包含了类或者方法的定义。对于编译型的语言,比如C#中的一个.cs文件,Java中的一个.java或者编译后的.class文件可以认为是一个模块(但常常不表述为模块);对于解释型的语言会更加直观些,比如PHP的....