我最近读了关于getattr()函数的文章。问题是我仍然不能理解它的用法。我对getattr()的唯一理解是,getattr(li,“pop”)与调用li.pop相同。
我不理解书中提到如何使用它来获取函数的引用,而直到运行时才知道它的名称。也许这就是我在编程方面的新手。谁能解释一下这个问题?我何时以及如何使用它?
我最近读了关于getattr()函数的文章。问题是我仍然不能理解它的用法。我对getattr()的唯一理解是,getattr(li,“pop”)与调用li.pop相同。
我不理解书中提到如何使用它来获取函数的引用,而直到运行时才知道它的名称。也许这就是我在编程方面的新手。谁能解释一下这个问题?我何时以及如何使用它?
当前回答
我认为这个例子是不言自明的。它运行第一个参数的方法,其名称在第二个参数中给出。
class MyClass:
def __init__(self):
pass
def MyMethod(self):
print("Method ran")
# Create an object
object = MyClass()
# Get all the methods of a class
method_list = [func for func in dir(MyClass) if callable(getattr(MyClass, func))]
# You can use any of the methods in method_list
# "MyMethod" is the one we want to use right now
# This is the same as running "object.MyMethod()"
getattr(object,'MyMethod')()
其他回答
下面是一个快速而简单的示例,演示了一个类如何根据使用getattr()执行的操作系统来触发save方法的不同版本。
import os
class Log(object):
def __init__(self):
self.os = os.name
def __getattr__(self, name):
""" look for a 'save' attribute, or just
return whatever attribute was specified """
if name == 'save':
try:
# try to dynamically return a save
# method appropriate for the user's system
return getattr(self, self.os)
except:
# bail and try to return
# a default save method
return getattr(self, '_save')
else:
return getattr(self, name)
# each of these methods could have save logic specific to
# the system on which the script is executed
def posix(self): print 'saving on a posix machine'
def nt(self): print 'saving on an nt machine'
def os2(self): print 'saving on an os2 machine'
def ce(self): print 'saving on a ce machine'
def java(self): print 'saving on a java machine'
def riscos(self): print 'saving on a riscos machine'
def _save(self): print 'saving on an unknown operating system'
def which_os(self): print os.name
现在让我们在一个例子中使用这个类:
logger = Log()
# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along
# somewhere else as 1st class:
save_func()
# or you can just call it directly:
logger.save()
# other attributes will hit the else
# statement and still work as expected
logger.which_os()
我有时使用getattr(..)在代码中使用属性之前惰性地初始化次要属性。
比较以下内容:
class Graph(object):
def __init__(self):
self.n_calls_to_plot = 0
#...
#A lot of code here
#...
def plot(self):
self.n_calls_to_plot += 1
:
class Graph(object):
def plot(self):
self.n_calls_to_plot = 1 + getattr(self, "n_calls_to_plot", 0)
The advantage of the second way is that n_calls_to_plot only appears around the place in the code where it is used. This is good for readability, because (1) you can immediately see what value it starts with when reading how it's used, (2) it doesn't introduce a distraction into the __init__(..) method, which ideally should be about the conceptual state of the class, rather than some utility counter that is only used by one of the function's methods for technical reasons, such as optimisation, and has nothing to do with the meaning of the object.
我在Python2.7.17中尝试过
有些人已经回答了。不过我已经试过打电话了 getattr(obj, 'set_value'),这没有执行set_value方法,所以我改为getattr(obj, 'set_value')()——>这有助于调用相同的。
示例代码:
示例1:
class GETATT_VERIFY():
name = "siva"
def __init__(self):
print "Ok"
def set_value(self):
self.value = "myself"
print "oooh"
obj = GETATT_VERIFY()
print getattr(GETATT_VERIFY, 'name')
getattr(obj, 'set_value')()
print obj.value
getattr的一个非常常见的用例是将数据映射到函数。
例如,在Django或Pylons这样的web框架中,getattr可以直接将web请求的URL映射到将要处理它的函数。例如,如果你看一下Pylons的路由,你会发现(至少在默认情况下)它分割了一个请求的URL,比如:
http://www.example.com/customers/list
分为“客户”和“列表”。然后它搜索名为CustomerController的控制器类。假设它找到该类,它创建该类的实例,然后使用getattr获取其list方法。然后调用该方法,将请求作为参数传递给它。
一旦你掌握了这个思想,扩展web应用程序的功能就变得非常容易:只需向控制器类添加新的方法,然后在页面中创建链接,为这些方法使用适当的url。所有这些都是由getattr实现的。
getattr()在Python中实现switch语句的另一种用法。它使用两个反射来获取大小写类型。
import sys
class SwitchStatement(object):
""" a class to implement switch statement and a way to show how to use gettattr in Pythion"""
def case_1(self):
return "value for case_1"
def case_2(self):
return "value for case_2"
def case_3(self):
return "value for case_3"
def case_4(self):
return "value for case_4"
def case_value(self, case_type=1):
"""This is the main dispatchmethod, that uses gettattr"""
case_method = 'case_' + str(case_type)
# fetch the relevant method name
# Get the method from 'self'. Default to a lambda.
method = getattr(self, case_method, lambda: "Invalid case type")
# Call the method as we return it
return method()
def main(_):
switch = SwitchStatement()
print swtich.case_value(_)
if __name__ == '__main__':
main(int(sys.argv[1]))