本文将分享我们是否真的需要python中的@staticmethod装饰器来声明静态方法的详细内容,此外,我们还将为大家带来关于(转)python3-staticmethod与classmethod、
本文将分享我们是否真的需要python中的@staticmethod装饰器来声明静态方法的详细内容,此外,我们还将为大家带来关于(转)python3-staticmethod与classmethod、python - 静态方法 staticmethod、类方法 classmethod、属性方法 property、python @classmethod @staticmethod、python @classmethod和@staticmethod的区别的相关知识,希望对你有所帮助。
本文目录一览:- 我们是否真的需要python中的@staticmethod装饰器来声明静态方法
- (转)python3-staticmethod与classmethod
- python - 静态方法 staticmethod、类方法 classmethod、属性方法 property
- python @classmethod @staticmethod
- python @classmethod和@staticmethod的区别
我们是否真的需要python中的@staticmethod装饰器来声明静态方法
我很好奇为什么我们需要@staticmethod
装饰器将method声明为static
。我正在阅读有关Python中的静态方法的信息,并且我知道静态方法可以在不实例化其类的情况下被调用。因此,我尝试了下面的两个示例,但是两者都相同:
class StatMethod:
def stat():
print("without Decorator")
class StatMethod_with_decorator:
@staticmethod
def stat():
print("With Decorator")
如果我stat()
直接在类上调用该方法,则都将打印/显示以下值:
>> StatMethod.stat()
without Decorator
>> StatMethod_with_decorator.stat()
With Decorator
(转)python3-staticmethod与classmethod
原文:https://blog.csdn.net/youngbit007/article/details/68957848
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/youngbit007/article/details/68957848
classmethod:类方法
staticmethod:静态方法
在Python中,静态方法和类方法都是可以通过类对象和类对象实例访问。但是区别是:
@classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法。 类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例。
普通对象方法至少需要一个self参数,代表类对象实例
类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。
对于类方法,可以通过类来调用,就像C.f(),有点类似C++中的静态方法, 也可以通过类的一个实例来调用,就像C().f(),这里C(),写成这样之后它就是类的一个实例了。
静态方法则没有,它基本上跟一个全局函数相同,一般来说用的很少
classmethod必须使用类对象作为第一个参数,而staticmethod则可以不传递任何参数。
class Date:
def __init__(self,day=0, month=0, year=0):
self.day=day
self.month = month
self.year = year
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int,date_as_string.split(''-''))
my_date = cls(day, month, year)
return my_date
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split(''-''))
return day <= 31 and month <= 12 and year <= 3999
if __name__ == ''__main__'':
my_date = Date.from_string(''11-09-2012'')
print(my_date.day, my_date.month,my_date.year)
is_date = Date.is_date_valid(''13-13-2012'')
print(is_date)
outputs:
11 9 2012
False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
在来看另外的例子,为了验证有子类继承时,子类调用该类方法时,传入的类变量cls是子类,而非父类
class A:
@classmethod
def cm(cls):
print(''类方法cm(cls)调用者:'', cls.__name__)
@staticmethod
def sm():
print(''静态方法sm()被调用'')
class B(A):
pass
A.cm() # 类方法cm(cls)调用者: A
B.cm() # 类方法cm(cls)调用者: B
A.sm() # 静态方法sm()被调用
B.sm() # 静态方法sm()被调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
下面我们来看为什么要用到staticmethod与classmethod。
class Kls:
def __init__(self,data):
self.data = data
def printd(self):
print(self.data)
ik1=Kls(''arun'')
ik2=Kls(''seema'')
ik1.printd()
ik2.printd()
# 如果现在我们想写一些仅仅与类交互而不是和实例交互的方法会怎么样呢? 我们可以在类外面写一个简单的方法来做这些,
# 但是这样做就扩散了类代码的关系到类定义的外面. 如果像下面这样写就会导致以后代码维护的困难:
def get_no_of_instances(cls_obj):
return cls_obj.no_inst
class Kls:
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print(get_no_of_instances(Kls)) # 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
应用classmethod
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
@classmethod
def get_no_of_instance(cls_obj):
return cls_obj.no_inst
ik1 = Kls()
ik2 = Kls()
print(ik1.get_no_of_instance())
print(Kls.get_no_of_instance())
# 2
# 2
1
2
3
4
5
6
7
8
9
10
11
12
13
@staticmethod
经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法
python - 静态方法 staticmethod、类方法 classmethod、属性方法 property
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 内置方法 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()
- 报错信息
如果换成
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()
- 报错:
- 方法不能正常调用。如果要调用,如下:
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))
六:元类
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))
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 @classmethod @staticmethod
@classmethod means:
when this method is called, we pass the class as the first argument instead of the instance of that class. This means you can use the class and its properties inside that method rather than a particular instance.
@staticmethod means:
when this method is called, we don''t pass an instance of the class to it .This means you can put a function inside a class but you can''t access the instance of that class (this is useful when your method does not use the instance).
#!/usr/bin/python
#coding:utf-8
class Person:
def __init__(self):
print "init"
@staticmethod
def s_sayHello(hello):
print "fun:s_sayhello %s" %hello
@classmethod
def c_introduce(clazz,hello):
clazz.s_sayHello(hello)
def hello(self,hello):
self.s_sayHello(hello)
def main():
print "Person.s_sayHello:"
Person.s_sayHello("Person:s_sayHello!")
print "Person.c_introduce"
Person.c_introduce("Person:c_introduce!");print "*"* 20;p=Person()
p.s_sayHello("p:s_sayHello!")
p.c_introduce("p:c_introduce!")
p.hello("p:hello!")
if __name__==''__main__'':
main()
输出
Person.s_sayHello:
fun:s_sayhello Person:s_sayHello!
Person.c_introduce
fun:s_sayhello Person:c_introduce!
********************
init
fun:s_sayhello p:s_sayHello!
fun:s_sayhello p:c_introduce!
fun:s_sayhello p:hello!
python @classmethod和@staticmethod的区别
也许一些例子会有帮助:注意foo
, class_foo
和static_foo
参数的区别:
class A(object):
a = ''a''
def __init__(self):
self.b = ''b''
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print cls.static_foo(''2'')
cls.name = ''A1''
print dir(cls)
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
a=A()
下面是一个对象实体调用方法的常用方式.对象实体a
被隐藏的传递给了第一个参数.
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)
用classmethod装饰,隐藏的传递给第一个参数的是对象实体的类(class A
)而不是self
.
a.class_foo(1)
# executing class_foo(<class ''__main__.A''>,1)
你也可以用类调用class_foo
.实际上,如果你把一些方法定义成classmethod
,那么实际上你是希望用类来调用这个方法,而不是用这个类的实例来调用这个方法.A.foo(1)
将会返回一个TypeError
错误, A.class_foo(1)
将会正常运行:
A.foo(1)
#TypeError: unbound method foo() must be called with A instance as first argument (got str instance instead)
# 这时可想到把示例化的a传进去怎么样?结果证实可行,和a.foo(1)效果一样,但不建议这样使用
# 其实f1 = A.foo, a = A(), f2 = a.foo, f1是unbound method,f2是bound method
# 具体可见https://my.oschina.net/u/914655/blog/1546281
A.foo(a, 1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)
A.class_foo(1)
# executing class_foo(<class ''__main__.A''>,1)
用staticmethod来装饰,不管传递给第一个参数的是self
(对象实体)还是cls
(类).它们的表现都一样:
a.static_foo(1)
# executing static_foo(1)
A.static_foo(''hi'')
# executing static_foo(hi)
静态方法被用来组织类之间有逻辑关系的函数.
foo
只是个函数,但是当你调用a.foo
的时候你得到的不仅仅是一个函数,你得到的是一个第一个参数绑定到a
的"加强版"函数. python解析器会自动把a示例绑定到foo的第一个参数参数上
a
绑定了foo
.下面可以知道什么叫"绑定"了:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
如果使用a.class_foo
, 是A
绑定到了class_foo
而不是实例a
.
print(a.class_foo)
# <bound method type.class_foo of <class ''__main__.A''>>
最后剩下静态方法,说到底它就是一个函数. a.static_foo
只是返回一个不带参数绑定的函数. static_foo
和a.static_foo
只需要一个参数.
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
总结:
- 普通类方法:第一个参数必须传,作为接收
类实例对象
的参数。也即持有类实例对象,需要实例化的类才能调用或者直接把实例化参数传入第一个,见上面 - @classmethod(类方法): 第一个参数必须传,作为接收
类对象
的参数。也即持有类对象,在不需实例化的情况下调用类的属性等 - @staticmethod(静态方法):
区别本质有了,具体几个应用如下:
最直接应用就是,加了这2个装饰器,就可以不需要实例化,直接通过 类名.函数名()
来调用,有利于组织代码,把属于某个类的函数,但又不需实例化的给放进类里去,同时有利于命名空间的整洁。
1. 构造多个构造函数
由于python里没有java的重载机制(java里同方法名不同参数认为是不同的方法,python里只要方法名唯一),可通过classmethod的特性构造多个构造函数
class Date(object):
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
比如Date类,我们要实例化它,必须传入day, month, year
加入我们有个string_date = ''11-4-2017''
必须按如下方式处理
day, month, year = map(int, string_date.split(''-''))
date1 = Date(day, month, year)
c++ java等语言有重载的特性,但python没有,这时我们就可以通过classmethod来实现
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split(''-''))
date1 = cls(day, month, year)
return date1
# 现在直接通过调用from_string即可
date2 = Date.from_string(''11-09-2012'')
# 而且有以下好处
# 1. 针对此类的日期解析函数在本类里,方便管理,而且可重用
# 2. cls是一个持有类本身的对象,而不是类的一个实例。这很酷,因为如果我们继承我们的Date类,所有的孩子也将有from_string定义。
接着上面,假如字符串格式不是''dd-mm-yyyy''格式,执行from_string就不会得到想要的结果,这时我们要检验这个值,此时staticmethod就会很合适
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split(''-''))
return day <= 31 and month <= 12 and year <= 3999
# usage:
is_date = Date.is_date_valid(''11-09-2012'')
今天关于我们是否真的需要python中的@staticmethod装饰器来声明静态方法的介绍到此结束,谢谢您的阅读,有关(转)python3-staticmethod与classmethod、python - 静态方法 staticmethod、类方法 classmethod、属性方法 property、python @classmethod @staticmethod、python @classmethod和@staticmethod的区别等更多相关知识的信息可以在本站进行查询。
本文标签: