我正在自学Python,我最近的一课是Python不是Java,所以我刚刚花了一段时间把我所有的Class方法变成了函数。
我现在意识到,我不需要使用Class方法来做我在Java中使用静态方法所做的事情,但现在我不确定什么时候我会使用它们。我能找到的所有关于Python类方法的建议都是,像我这样的新手应该避开它们,而标准文档在讨论它们时是最不透明的。
谁有一个在Python中使用类方法的好例子,或者至少有人能告诉我什么时候可以合理地使用类方法吗?
我正在自学Python,我最近的一课是Python不是Java,所以我刚刚花了一段时间把我所有的Class方法变成了函数。
我现在意识到,我不需要使用Class方法来做我在Java中使用静态方法所做的事情,但现在我不确定什么时候我会使用它们。我能找到的所有关于Python类方法的建议都是,像我这样的新手应该避开它们,而标准文档在讨论它们时是最不透明的。
谁有一个在Python中使用类方法的好例子,或者至少有人能告诉我什么时候可以合理地使用类方法吗?
当前回答
我最近想要一个非常轻量级的日志类,它可以根据可编程设置的日志级别输出不同数量的输出。但我不想每次输出调试消息、错误或警告时都实例化这个类。但是我还想封装这个日志记录工具的功能,并使其在不声明任何全局变量的情况下可重用。
所以我使用类变量和@classmethod装饰器来实现这一点。
使用简单的Logging类,我可以做到以下几点:
Logger._level = Logger.DEBUG
然后,在我的代码中,如果我想输出一堆调试信息,我就必须编写代码
Logger.debug( "this is some annoying message I only want to see while debugging" )
错误是可以改正的
Logger.error( "Wow, something really awful happened." )
在“生产”环境中,我可以指定
Logger._level = Logger.ERROR
现在,将只输出错误消息。调试消息将不会被打印。
这是我的班级:
class 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
@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
还有一些代码可以稍微测试一下:
def logAll() :
Logger.debug( "This is a Debug message." )
Logger.info ( "This is a Info message." )
Logger.warn ( "This is a Warn message." )
Logger.error( "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()
其他回答
我也问过自己几次同样的问题。尽管这里的人试图努力解释它,恕我直言,我找到的最好的答案(也是最简单的)答案是Python文档中对Class方法的描述。
还有对静态方法的引用。如果有人已经知道实例方法(我假设是这样),这个答案可能是把它们放在一起的最后一块……
关于这个主题的进一步和更深入的阐述也可以在文档中找到: 标准类型层次结构(向下滚动到实例方法部分)
当用户登录我的网站时,user()对象从用户名和密码实例化。
如果我需要一个没有用户在那里登录的用户对象(例如,一个管理用户可能想要删除另一个用户帐户,所以我需要实例化该用户并调用它的delete方法):
我有类方法来获取用户对象。
class User():
#lots of code
#...
# more code
@classmethod
def get_by_username(cls, username):
return cls.query(cls.username == username).get()
@classmethod
def get_by_auth_id(cls, auth_id):
return cls.query(cls.auth_id == auth_id).get()
诚实?我从未发现staticmethod或classmethod的用途。我还没有看到一个操作不能使用全局函数或实例方法来完成。
如果python像Java那样使用private和protected成员,情况将有所不同。在Java中,我需要一个静态方法来访问实例的私有成员来做一些事情。在Python中,很少需要这样做。
通常,我看到人们使用静态方法和类方法,而他们真正需要做的只是更好地使用python的模块级名称空间。
替代构造函数是经典的例子。
工厂方法(替代构造函数)确实是类方法的经典例子。
基本上,类方法适用于任何您希望有一个方法自然地适合类的名称空间,但不与类的特定实例相关联的时候。
例如,在excellent unipath模块中:
当前目录
Path.cwd () 返回实际的当前目录;例如,路径(“/ tmp / my_temp_dir”)。这是一个类方法。 .chdir () 使self为当前目录。
由于当前目录是进程范围的,cwd方法没有应该与之关联的特定实例。但是,将cwd更改为给定Path实例的目录确实应该是一个实例方法。
嗯…因为Path.cwd()确实返回了一个Path实例,我猜它可以被认为是一个工厂方法…