python类⽅法的作⽤-python:类⽅法的⽬的是什么?
我正在⾃学Python,⽽我最近的经验是Python不是Java,所以我花了⼀些时间将所有的类⽅法转换成函数。
我现在意识到,我不需要使⽤类⽅法来完成我在Java中使⽤static⽅法所做的⼯作,但是现在我不确定什么时候使⽤它们。关于Python类⽅法,我能到的所有建议都是像我这样的新⼿应该避免使⽤的,并且在讨论它们时,标准⽂档是最不透明的。
有没有⼈有在Python中使⽤类⽅法的好例⼦,或者⾄少有⼈能告诉我什么时候可以合理地使⽤类⽅法?
类⽅法⽤于当您需要不特定于任何特定实例,但仍然以某种⽅式涉及类的⽅法时。它们最有趣的地⽅是可以被⼦类覆盖,这在Java的静态⽅法或Python的模块级函数中是不可能的。
如果您有⼀个类MyClass和⼀个在MyClass(⼯⼚、依赖注⼊存根等)上操作的模块级函数,那么将它设置为classmethod。然后它将对⼦类可⽤。
⼯⼚⽅法(可选构造函数)确实是类⽅法的⼀个经典例⼦。
基本上,只要您希望有⼀个⽅法⾃然地适合于类的名称空间,但⼜不与类的特定实例关联,那么类⽅法就⾮常适合。
例如,在优秀的unipath模块中:当前⽬录
Path.cwd()返回当前⽬录;例如,Path("/tmp/my_temp_dir")。这是⼀个类⽅法。.chdir()使self成为当前⽬录。
由于当前⽬录是进程范围的,cwd⽅法没有应该与之关联的特定实例。但是,将cwd更改为给定的Path实例的⽬录确实应该是⼀个实例⽅法。
嗯…由于Path.cwd()确实返回了⼀个Path实例,我想它可以被认为是⼀个⼯⼚⽅法……
"当函数作为对象的⽅法被调⽤时,它会⽆声地传递"——我认为这并不准确。在Python中,没有什么是"悄⽆声息地传递"的。在我看
来,Python在这个意义上⽐Ruby更有意义(除了super())。当属性被设置或读取时,"魔法"就会发⽣。Python中的调⽤h(arg)(与Ruby不同)只表⽰(h)(arg)。任何地⽅都不会⽆声地传递任何东西,h只是⼀个可调⽤的对象,它接受的参数⽐创建它的函数少⼀个。
为来⾃其他共同语⾔的⼈量⾝定制答案是有意义的。然⽽,这段对话中缺少的⼀件将其联系在⼀起的
事情是Python描述符的概念。函数是描述符,这就是当函数是类的属性时,第⼀个参数"⾃动地"传递给实例的⽅式。它也是如何实现类⽅法的,在how to I链接中提供了⼀个纯python实现。事实上,它也是⼀个装饰器是⼀种辅助
这样考虑:普通⽅法对于隐藏分派的细节很有⽤:您可以输⼊myobj.foo(),⽽不⽤担⼼myobj对象的类或它的⽗类之⼀是否实现了foo()⽅法。类⽅法与此完全类似,但是使⽤的是类对象:它们允许您调⽤MyClass.foo(),⽽不必担⼼foo()是由MyClass专门实现的,因为它需要⾃⼰的专门化版本,还是让它的⽗类处理调⽤。
在创建实际实例之前进⾏设置或计算时,类⽅法是必不可少的,因为在实例存在之前,显然不能将实例⽤作⽅法调⽤的分派点。⼀个很好的例⼦可以在SQLAlchemy源代码中查看;请看下⾯链接中的dbapi()类⽅法:
dbapi()⽅法可以看出,⼀个数据库后端使⽤导⼊特定于供应商的数据库库需要随需应变,是⼀个类⽅法,因为它需要运⾏在⼀个特定的实例开始创建数据库连接,但它绝不是⼀个简单的函数或静态函数,因为他们希望它能够调⽤其他⽀持⽅法可能同样需要写更具体⼦类的⽗类。如果您分派给函数或静态类,那么您将"忘记"并丢失关于哪个类正在进⾏初始化的知识。
是的…⾸先想到的是⼯⼚的⽅法。与此同时,还需要实现单例模式,⽐
如:getAndOptionallyCreateSomeSingleInstanceOfSomeResource()
在python中,这些是静态⽅法,⽽不是类⽅法。
我最近想要⼀个⾮常轻量级的⽇志类,它可以根据可编程设置的⽇志级别输出不同数量的输出。但我还想封装这个⽇志⼯具的功能,使其⽆需声明任何全局变量即可重⽤。
因此,我使⽤类变量和@classmethod装饰器来实现这⼀点。
使⽤我的简单⽇志类,我可以做以下事情:
1Logger._level = Logger.DEBUG
然后,在我的代码中,如果我想输出⼀堆调试信息,我只需编写代码
1Logger.debug("this is some annoying message I only want to see while debugging" )错误可以被排除
<("Wow, something really awful happened." )
在"⽣产"环境中,我可以指定
1Logger._level = Logger.ERROR
现在,只输出错误消息。调试消息将不会打印。
这是我的类:
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
30
31
32
33
34
35
36
37
38
39
40
41class Logger :
""" Handles logging of debugging and error messages. """ DEBUG = 5
INFO = 4
WARN = 3
ERROR = 2
FATAL = 1
_level = DEBUG
def __init__( self ) :
Logger._level = Logger.DEBUG
python新手代码例子
@classmethod
def isLevel( cls, level ) :
return cls._level >= level
@classmethod
def debug( cls, message ) :
if cls.isLevel( Logger.DEBUG ) :
print"DEBUG: " + message
@classmethod
def info( cls, message ) :
if cls.isLevel( Logger.INFO ) :
print"INFO : " + message
@classmethod
def warn( cls, message ) :
if cls.isLevel( Logger.WARN ) : print"WARN : " + message
@classmethod
def error( cls, message ) :
if cls.isLevel( Logger.ERROR ) : print"ERROR: " + message
@classmethod
def fatal( cls, message ) :
if cls.isLevel( Logger.FATAL ) : print"FATAL: " + message
还有⼀些测试它的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def logAll() :
Logger.debug("This is a Debug message." ) Logger.info ("This is a Info message." ) Logger.warn ("This is a Warn message." ) ("This is a Error message." )
Logger.fatal("This is a Fatal message." )
if __name__ == "__main__" :
print"Should see all DEBUG and higher"
Logger._level = Logger.DEBUG
logAll()
print"Should see all ERROR and higher"
Logger._level = Logger.ERROR
logAll()
我明⽩了。但是,如果我只是想对⼀个不需要MyClass的⽅法进⾏分类,但在另⼀个MyClass中进⾏分组⼜有什么意义呢?我可以考虑把它移到helper模块。
我有⼀个和第⼀个问题有关的问题,你可以同时回答吗?调⽤对象的类⽅法的⽅法是"更好"还是"更习惯":obj.cls_mthd(...)还是
type(obj).cls_mthd(...)?
替代构造函数就是⼀个经典的例⼦。
我认为最明确的答案是AmanKow的⼀个。归结起来就是你想要如何组织你的代码。你可以把所有的东西都写成模块级的函数,这些函数被封装在模块的命名空间中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。