77

我正在找人解释如何使用的基础知识,而不是使用setattr().

我的问题是试图使用一个类方法/函数来返回数据,然后将其放入另一个方法/函数中。在这种情况下,也许一种更简单的方法会更好,但我试图了解类是如何工作/使用的。这个问题似乎取决于setattr(),这是我尝试相当简单地使用它。

虽然这不是同一个问题,但我一直在关注Python The Hard Way,ex42while第 18-41 行的循环。

我尝试编写一个\__init__(), 并getattr()改为使用,认为可能需要在类的命名空间中,但这似乎没有帮助。

#! /bin/python2.6

class HolyGrail(object):

    def __init__(self):
        self.start = 'start_at_init'

    # function definition in question:
    # TypeError: 'str' object is not callable

    def run_it(self):
        start = setattr(self, 'name', 'get_thing')
        start = self.name

        # Something wrong here?
        value_returned = start() #I believe this == self.get_thing()
        use_it(value_returned)

    """
    # alternate function definitions
    # NameError: global name 'start' is not defined

    def __init__(self):
        self.start = 'get_thing'

    def run_it(self):
        go_do_it = getattr(self, start)
        first_output = go_do_it()
        use_it(first_output)
    """

    def get_thing(self):
        return "The Knights Who Say ... Ni!"

    def use_it(self, x):
        print x
        print "We want a shrubbery!"

my_instance = HolyGrail()
my_instance.run_it()

@Karl Knechtel、@Amber、@Chris Morgan 感谢您的帮助。

我想我现在可以解释我自己的答案了!这需要我更好地把握作为对象的自我。这是一个实例名称,它被标记为属性之类的东西。

类可以是 Town,然后。 getattr用它的名字寻找房子,所以你很快就可以打电话给它了,如果你找不到房子,就会想出一个不同的地方——getattr有了“名字”,你就去找它。使从一个函数到另一个动态的步骤作为奖励,您可能有一个默认值,对于获取回退默认方法很有用——连接失败还是什么?

setattr建造一所房子并给它起一个名字,这样你以后可以打电话给它。你可能会重建这所房子,或者如果你找不到它就去一个特定的地方。--setattr创建一个属性名称并给出或更改它的值,以便稍后调用 也许用户关闭声音,然后未来的方法不会输出任何音频。

我可以通过多种方式编写函数,但无需更改任何属性:

def run_it(self):
    yo = getattr(self, 'get_thing')
    answer = yo()
    setattr(self, 'deal_accepted', self.use_it) #really ott
    no = getattr(self, 'deal_accepted')
    no(answer)

正确更正的代码:

def run_it(self):
    value_returned = self.get_thing()
    self.use_it(value_returned)
4

6 回答 6

95

据我所知, Python 文档说了所有需要说的话。

setattr对象名称

这是 的对应物getattr()。参数是一个对象、一个字符串和一个任意值。该字符串可以命名现有属性或新属性。如果对象允许,该函数将值分配给属性。例如,setattr(x, 'foobar', 123)等价于x.foobar = 123

如果这还不够,请解释你不明白的地方。

于 2012-03-05T03:15:31.353 回答
80

您正在设置self.name字符串 "get_thing"而不是函数get_thing

如果你想self.name成为一个函数,那么你应该将它设置为一个:

setattr(self, 'name', self.get_thing)

但是,这对于您的其他代码完全没有必要,因为您可以直接调用它:

value_returned = self.get_thing()
于 2012-03-05T03:14:12.690 回答
14

Setattr: 我们使用setattr为我们的类实例添加一个属性。我们传递类实例、属性名称和值。并使用getattr我们检索这些值

例如

Employee = type("Employee", (object,), dict())

employee = Employee()

# Set salary to 1000
setattr(employee,"salary", 1000 )

# Get the Salary
value = getattr(employee, "salary")

print(value)
于 2017-03-08T10:29:48.107 回答
5

为了添加其他答案,我发现的一个常见用例setattr()是使用配置时。将文件(.ini 文件或其他文件)中的配置解析为字典是很常见的。所以你最终会得到类似的东西:

configs = {'memory': 2.5, 'colour': 'red', 'charge': 0, ... }

如果您想将这些配置分配给要存储和传递的类,您可以进行简单的分配:

MyClass.memory = configs['memory']
MyClass.colour = configs['colour']
MyClass.charge = configs['charge']
...

但是,循环遍历配置要容易得多,也不那么冗长,setattr()就像这样:

for name, val in configs.items():
    setattr(MyClass, name, val)

只要您的字典键具有正确的名称,它就可以很好地工作并且美观整洁。

*注意,dict 键必须是字符串,因为它们将是类对象名称。

于 2019-05-20T14:23:15.653 回答
4

假设您想为以前未用代码编写的实例赋予属性。就是这样setattr()做的。它需要类的实例self以及要设置的键和值。

class Example:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
于 2017-08-26T18:31:06.387 回答
1

关于您的代码,让我印象深刻的第一件事是您将 start 设置为setattr.

start = setattr(self, 'name', 'get_thing')
start = self.name

# Something wrong here?
value_returned = start() #I believe this == self.get_thing()
use_it(value_returned)

的返回值为setattr无。它是执行并执行任务但不返回值的操作。类似于调用类似的东西exit(),操作只是运行。从你的shell输入python,你会看到

a = exit() #exits your program

将 a 设置为print('x')执行类似于 exit 和类似 your setattr,但是,调用 a 不会调用我们的方法。

a = print('15') #returns 15
a #returns None

如果您希望能够setattr从您的类中调用,您可以为它定义一个方法。

def setAtrrClassInstance(self,name,value):  #This returns None
    setattr(self,name,value)
于 2021-09-03T16:03:35.953 回答