提取分配的变量名称
请参阅下面的更新
我什至不知道如何为我的问题制作一个简短的标题。
在一个类中,我有 StringField
类的一些类属性:
class Authors(Table):
# id field is already present
first_name = StringField(maxLength=100)
last_name = StringField(maxLength=100)
StringField
构造函数可能会接收一个名为 name
的参数。如果没有给出,我希望它等于类属性的名称(上面示例中的first_name
,last_name
)。
是否可以提取创建的实例将分配给的变量的名称? 我想我必须使用 inspect
模块?
我看到 Django 是这样做的:
每种字段类型,除了ForeignKey、ManyToManyField 和 OneToOneField,采用可选的第一个位置参数 - a 详细的名称。如果没有给出详细名称,Django 将 使用字段的属性名称自动创建它,转换 下划线改为空格。
在此示例中,详细名称是“人的名字”:
first_name = models.CharField("人的名字", max_length=30)
在此示例中,详细名称是“first name”:
first_name = models.CharField(max_length=30)
但我在 Django 1.3.1 源代码中找不到正在执行我需要的部分。
更新:
简化:
class Field():
def __init__(self, field_name=None):
if not field_name:
field_name = ??? # some magic here to determine the name
print(field_name)
class Table():
first_name = Field()
last_name = Field()
运行此命令应打印 first_name
和 last_name
解决方案:
class Field():
def __init__(self, name=None):
self._name = name
class Table():
first_name = Field()
last_name = Field()
for attrName, attr in Table.__dict__.items():
if isinstance(attr, Field):
if attr._name is None:
attr._name = attrName
print(Table.first_name._name)
print(Table.last_name._name)
See the update below
I even don't know how to make a short title for my problem.
In a class I have some class attributes of StringField
class:
class Authors(Table):
# id field is already present
first_name = StringField(maxLength=100)
last_name = StringField(maxLength=100)
StringField
constructor may receive an argument called name
. If it's not given, i want it to be equal to class attribute's name (first_name
, last_name
in the example above).
Is it possible to extract the name of the variable the created instance is going to be assigned to?
I guess i have to use inspect
module?
I see Django does this:
Each field type, except for ForeignKey, ManyToManyField and
OneToOneField, takes an optional first positional argument -- a
verbose name. If the verbose name isn't given, Django will
automatically create it using the field's attribute name, converting
underscores to spaces.In this example, the verbose name is "person's first name":
first_name = models.CharField("person's first name", max_length=30)
In this example, the verbose name is "first name":
first_name = models.CharField(max_length=30)
But i don't find in Django 1.3.1 source code the part which is doing what i need.
UPDATE:
To simplify:
class Field():
def __init__(self, field_name=None):
if not field_name:
field_name = ??? # some magic here to determine the name
print(field_name)
class Table():
first_name = Field()
last_name = Field()
Running this should print first_name
and last_name
SOLUTION:
class Field():
def __init__(self, name=None):
self._name = name
class Table():
first_name = Field()
last_name = Field()
for attrName, attr in Table.__dict__.items():
if isinstance(attr, Field):
if attr._name is None:
attr._name = attrName
print(Table.first_name._name)
print(Table.last_name._name)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不知道姜戈是怎么做到的。但您可以这样做:
下面是上述代码的实际运行示例:
WantFixup
类有两个用途。首先,所有继承自它的类都可以使用 isinstance() 来检测;如果我们的对象实例名为o
,我们可以像isinstance(o, WantFixup)
一样测试它。其次,它为继承它的任何类提供了.new_instance()
方法函数。Container
类是可能需要修复的容器的示例。请注意,它继承自WantFixup
。WillFixup
类包含一个.__init__()
方法,该方法对从其继承的所有类执行修复。这只是循环遍历类字典中的所有内容,并为每个内容调用.new_instance()
方法函数,并传入名称。最后,
Name
类继承自WillFixup
,并包含两个Container
实例。因为它继承自WillFixup
,所以会调用WillFixup.__init__()
方法。从示例中可以看出,first_name
的.name
属性设置为'given name'
,但last_name
未设置,因此对其进行了修补,将其.name
属性设置为'last name'
。.__init__()
函数应该设置新的类实例。只要所有特殊的WantFixup
类实例都在父类中,.__init__()
方法就会自动循环遍历它们并设置它们。这里令人困惑的部分是,该实例已将
first_name
设置为已修补名称的Container
实例,并且实际上将用于存储内容。但是类Name
包含一个Container
实例,它仅用于存储类的名称,并作为.__init__()
的标记。代码>方法来查找。好的部分是魔法隐藏在基类中。
Container
和Name
类只需要从它们继承,但它们本身并不混乱。使用元编程可能有一种更灵活的方法来解决问题。
http://www.ibm.com/developerworks/linux/library /l-pymeta/index.html
此解决方案不是元类编程,但它是经过测试的工作代码。
编辑:这是代码的更改版本。原始代码旨在展示总体思路,但实际上并未初始化
Name
对象。实际上执行 init 并不难,所以我改变了它。I don't know how Django does it. But you could do it this way:
Here is an example of the above code in action:
The class
WantFixup
serves two purposes. First, all classes that inherit from it can be detected usingisinstance()
; if our object instance is namedo
, we can test it likeisinstance(o, WantFixup)
. Second, it provided the.new_instance()
method function to any class that inherits from it.The class
Container
is an example of a container that might need fixup. Note that it inherits fromWantFixup
.The class
WillFixup
contains a.__init__()
method that performs fixup on all classes that inherit from it. This simply loops over everything in the class dictionary, and calls the.new_instance()
method function for each one, passing in the name.Finally, class
Name
inherits fromWillFixup
and contains two instances ofContainer
. Because it inherits fromWillFixup
, the methodWillFixup.__init__()
is called. As you can see from the example,first_name
has a.name
attribute set to'given name'
butlast_name
wasn't set, so it is patched to have its.name
attribute set to'last name'
.The
.__init__()
function is supposed to set up the new class instance. As long as all the specialWantFixup
class instances are in the parent class, the.__init__()
method will automatically loop over them and set them up.The confusing part here is that the instance has
first_name
set to an instance ofContainer
that has the name patched, and will actually be used to store stuff. But the className
contains an instance ofContainer
that is just used to store the name of the class, and as a marker for the.__init__()
method to find.The good part is that the magic is hidden away in the base classes. The
Container
andName
classes just need to inherit from them, but are not themselves cluttered with stuff.There might be a slicker way to solve the problem using metaprogramming.
http://www.ibm.com/developerworks/linux/library/l-pymeta/index.html
This solution isn't metaclass programming, but it is tested, working code.
EDIT: This is a changed version of the code. The original code was intended to show the general idea, but didn't actually init the
Name
object. It's not hard to actually do the init, so I changed it.为了像示例中那样神奇地发生,Python 需要成为一种上下文相关的语言(据我所知,事实并非如此)。 Django 使用
ModelBase
元类(以及其他任务)为字段设置详细名称。基本上,元类的__new__
循环遍历类属性以获取属性名称,并将它们添加到 选项。你可以更直接一点,直接改变字段。这是一个 Python 2 示例:Python 3 几乎相同,但您使用
metaclass
类参数* 而不是__metaclass__
属性:您可以编写一个与 Python 2 和 3 中的元类 通过直接使用元类为容器创建中间基类,而不是
metaclass
参数或__metaclass__
属性:* 有关更改的原因,请参阅 PEP 3115:Python 3000 中的元类。
In order for the magic to happen as in the sample, Python would need to be a context-sensitive language (which is isn't, as far as I know, which isn't that far). Django uses the
ModelBase
meta-class to (among other tasks) set verbose names for the fields. Basically, the metaclass's__new__
loops over the class attributes to get the attribute names, adding them to the options. You can be a little more direct and alter the fields directly. Here's a Python 2 example:Python 3 is almost the same, but you use the
metaclass
class argument* rather than the__metaclass__
property:You can write a version that works with metaclasses in in Python 2 and 3 by creating an intermediate base class for the container using the metaclass directly, rather than the
metaclass
argument or__metaclass__
property:* For the reason for the change, see PEP 3115: Metaclasses in Python 3000.