python/django中setattr和对象操作的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12801586/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between setattr and object manipulation in python/django
提问by whatf
I have the following model:
我有以下模型:
class Ticket(models.Model):
title = models.CharField()
merged_to = models.ForeignKey("self", related_name='merger_ticket', null=True, blank=True)
looser_ticket = models.BooleanField(default=False)
There are couple of ways of manipulating the model:
有两种操作模型的方法:
First
第一的
ticket = Ticket.objects.get(pk=1)
ticket.title = "This is edit title"
ticket.merged_to_id = 2
ticket.looser_ticket = True
Second
第二
ticket = Ticket.objects.get(pk=1)
setattr(ticket, "title", "Edit Title")
setattr(ticket, "merged_to_id", 2)
setattr(ticket, "looser_ticket", True)
When I was manipulating the stuff, in views for the boolean value updation the first method did not work, however the second method worked. What is the difference between using first and second, and when they should be used?
当我操作这些东西时,在布尔值更新的视图中,第一种方法不起作用,但是第二种方法起作用。使用 first 和 second 有什么区别,什么时候应该使用它们?
Thanks!
谢谢!
采纳答案by miki725
This is more of a Python question.
这更像是一个 Python 问题。
Python is very dynamic language. You can code things (classes) ahead of time, or Python allows you to create classes completely dynamically at run-time. Consider the following example of a simple vector class. You can create/code the class ahead of time like:
Python 是一种非常动态的语言。您可以提前对事物(类)进行编码,或者 Python 允许您在运行时完全动态地创建类。考虑以下简单向量类的示例。您可以提前创建/编码类,例如:
class MyVector(object):
x = 0
y = 0
or you can create the class dynamically by doing:
或者您可以通过执行以下操作动态创建类:
fields = {'x':0, 'y':0}
MyVector = type('MyVector', (object,), fields)
The main difference between the methods is that for one you know the class attributes ahead of time, whereas for the second method as you can imagine, you can programmatically create the fieldsdictionary, therefore you can create completely dynamically class(es).
这些方法之间的主要区别在于,对于第一种方法,您提前知道类属性,而对于第二种方法,您可以想象,您可以通过编程方式创建fields字典,因此您可以完全动态地创建类。
So when you know the attributes of the class ahead of time, you can set class attributes using the object notation:
因此,当您提前知道类的属性时,您可以使用对象表示法设置类属性:
instance.attribute = value
Keep in mind that that is equivalent to:
请记住,这相当于:
instance.__setattr__("attribute", value)
However there are scenarios where you don't know the class attributes you will need to manipulate ahead of time. This is where you can use __setattr__function. However it is not recommended practice. So instead the recommendation is to use Python's build-in method setattrwhich internally calls the __setattr__method:
但是,在某些情况下,您不知道需要提前操作的类属性。这是您可以使用__setattr__功能的地方。但是,不推荐这种做法。因此,建议使用 Python 的内置方法setattr,该__setattr__方法在内部调用该方法:
setattr(instance, attribute, value)
Using this approach you can set attributes you don't know ahead of time or you can even loop of some dictand set values from dict:
使用这种方法,您可以提前设置您不知道的属性,或者您甚至可以循环一些dict并从 dict 设置值:
values = {
'title': 'This is edit title',
...
}
for k, v in values.items():
setattr(ticket, k, v)
Not sure why the regular notation did not work for. It probably has nothing to do with the method you used to set attributes.
不知道为什么常规符号不起作用。它可能与您用来设置属性的方法无关。
回答by dm03514
If you know the objects properties before hand you should probably be using the first method. Just assign property values directly.
如果您事先知道对象属性,您可能应该使用第一种方法。只需直接分配属性值。
The second can be useful when you need to dynamically assign a value to a property. Perhaps a user has the ability to change the values of a number of different attributes and you don't know which one will have a value before hand, you can dynamically add values
当您需要为属性动态分配值时,第二个很有用。也许用户有能力改变许多不同属性的值,而你事先不知道哪个会有值,你可以动态添加值
possible_fields = ['title', 'looser_ticket']
ticket = Ticket.objects.get(pk=1)
for field in possible_fields:
if request.GET.get(field):
setattr(ticket, field, request.GET[field])
The "not working" is probably not dependent on the way you are setting values, are you sure that you saved your changes afterwards??
“不工作”可能不取决于您设置值的方式,您确定之后保存了更改吗?

