【问题标题】:Difference between declaring a class with class vs Type?用类与类型声明类之间的区别?
【发布时间】: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


【解决方案1】:

这是一个很棒的工具。 是的,一个非常棒的工具,因为使用“类型”你可以传递任何参数,它会为你创建那个对象.. 假设您可以使用 consol 输入来传递此参数或使用某种网络在远程计算机上调用此函数。

但是对于“类”,您必须对类类型进行硬编码,这可能会使我们的程序不那么动态。

因此,它是构建动态和高级应用程序的绝佳实用程序。

【讨论】:

    猜你喜欢
    • 2015-11-03
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多