【发布时间】:2017-10-05 00:48:43
【问题描述】:
根据this tutorial(参见段落“简单元类使用”),这两种声明是有区别的:
>>> MyClass = type('MyClass', (), {})
>>> MyClass
<class '__main__.MyClass'>
和
>>> class Meta(type):
... pass
关于区别,教程是这样说的:
class 语句不仅仅是语法糖,它还做了一些额外的事情,比如设置足够的__qualname__ 和__doc__ 属性或调用__prepare__。
本教程是为 python 3 编写的,但表示将在 python 2 不同的情况下给出脚注。本段没有脚注
我找不到其他说同样事情的教程。事实上,我可以找到其他人saying that they are the same。在“类型的黑暗面”段落下,它谈到了两个声明:
我们可以通过以下方式达到完全相同的效果:
我提出问题的原因是我偶然发现了一种似乎存在差异的情况。类声明有效:
class Customers(Base):
__table__ = ERPTables.Customers
虽然类型声明不起作用:
type('Customers', (Base, ), {'__table__': ERPTables.Customers})
我一直把最好的留到最后,但是当我说工作时,我的意思是在 sqlAlchemy 的上下文中。类声明在以下代码中使用时会产生结果
query = session.query(BasisOfAutoPayment_DK)
pd.read_sql(query.limit(5).statement, session.bind)
虽然类型声明在完全相同的代码中使用时不起作用。
这是 sqlAlchemy,当然还有很多事情要做,但是在两个实例中都使用了相同的对象。相同的 Base 对象,相同的 Table 声明,相同的引擎。我认为差异就在这一边,但我试图控制它,我知道事实并非如此。这就是我现在询问这两个声明的原因。
编辑: 进一步检查这两个声明,我可以看到行为上的一些相似之处和不同之处。
相似度:
在做了类声明之后。调用类名会产生:
>>> Customers
__main__.Customers
这与您在进行类型声明时得到的响应完全相同:
>>> type('Customers', (Base, ), {'__table__': ERPTables.Customers})
__main__.Customers
然而,两者之间的一个很大区别是:
在类声明之后,您可以调用Customers 名称并获得刚刚显示的输出__main__.Customers。
然而,在类型声明之后,调用 Customers 名称会出现名称错误:
NameError: name 'Customers' is not defined
很明显为什么两者在 sqlAlchemy 查询中的行为不同。难怪如果找不到对象,它在类型版本中不起作用
【问题讨论】:
-
因为你必须这样做
Customer = type('Customers', (Base, ), {'__table__': ERPTables.Customers})否则名称Customer永远不会分配给。 -
这是不正确的。这里的问题是类型声明没有将类名分配给全局名称空间。这至少是我的看法,after getting help on my first, more sqlAlchemy centric question to SO@univerio 在这里给出了答案,为我解决了这个问题。我让他看看这个问题并给出他的解释,因为我认为这将有利于更多的人。
-
什么?这就是正是我在说什么!在此范围内执行
Customer = type('Customers', (Base, ), {'__table__': ERPTables.Customers})等效于globals()['Customer'] = type('Customers', (Base, ), {'__table__': ERPTables.Customers})。这不是“类型声明”。类型是type类型。调用type类型会创建该类型的新实例。type类型的实例是类。 -
是的,你的回答解释了两种完美声明方式的区别!我很抱歉这么愚蠢。
标签: python python-2.7 class