【问题标题】:Creating objects of a class via globals()[]通过 globals()[] 创建一个类的对象
【发布时间】:2021-10-14 11:21:46
【问题描述】:

我意识到不推荐我尝试做的事情,但现在我有兴趣追求它,以便更好地了解对象创建和globals()[] 的工作原理。

在下面的代码中,我可以使用globals()[]varList中的三个字符串元素转换为变量。

varList = ['var1', 'var2', 'var3']
for index, i in enumerate(varList):
    globals()[i] = index + 1
    print(varList[index], '=', globals()[i])
print(var1,var2,var3)

我可以通过我的两个 print() 电话确认这一点,它们给出:

var1 = 1
var2 = 2
var3 = 3

1 2 3

分别。

然而,虽然在创建类的对象时,我似乎拥有能够执行类似操作所需的所有正确部分,但我似乎无法将所有部分放在一起。

运行以下代码

class Cars:
    info = ['make', 'model', 'type', 'year']

def metaObject():
    attributeList = []
    myCar = Cars()

    for index, i in enumerate(myCar.info):
        attributeList += ['myCar.'+ i]
        myInfoList = ['Toyota', 'Prius', 'Sedan', 2010]
        
        print(attributeList[index],'=', myInfoList[index])

        globals()[attributeList[index]] = myInfoList[index]

        print(attributeList[index])
        print(globals()[attributeList[index]])

        print('\n')

    print(attributeList)
    print(myInfoList)

metaObject()

产生以下输出:

myCar.make = Toyota 
myCar.make
Toyota

myCar.model = Prius 
myCar.model
Prius


myCar.type = Sedan 
myCar.type
Sedan


myCar.year = 2010 
myCar.year
2010


['myCar.make', 'myCar.model', 'myCar.type', 'myCar.year']
['Toyota', 'Prius', 'Sedan', 2010]

但是,在我的脚本末尾添加print(myCar.make) 会导致错误NameError: name 'myCar' is not defined

我在这里遗漏了什么,在我看来 myCar 是在我的脚本的第 5 行定义的?

或者,如果在我的代码末尾——在调用 metaObject() 之后——我要添加

myCar = Cars()
myCar.make = 'someCarMaker'
print(myCar.make)

那么我会得到想要的结果someCarMaker

我需要在metaObject() 的定义中做什么/更改才能获得我想要的结果?

【问题讨论】:

  • 变量名中不能有.。至少在您了解类、对象甚至基本字典如何在 IMO 中工作之前,不要再乱用globals();这实际上是自学这些概念的最令人困惑的方式。 :)
  • 我觉得学习课程正是我想要做的。您对如何更好地进行此操作有更具体的建议吗?至于代码,如果我将以下代码添加为单独的代码行myCar = Cars()myCar.make = 'someCarMaker'print(myCar.make),那么我会得到所需的结果someCarMaker。但是,我很难理解为什么在我对metaObject() 的定义中没有发生这种情况。您能否提供一个示例,说明我如何能够在 metaObject() 中实现预期的结果
  • myCar.make = ... 不是对名称 myCar.make 的赋值;它是myCar.__setattr__('make', ...) 的缩写。这并不意味着您不能将 key 'myCar.make' 添加到 globals() 的值中;它是一个dict,就像任何其他的一样,只有一个更新全局命名空间如果适用
  • @ZwiTrader 不,不是。您正在混淆源代码字符串。您在全局命名空间中放置了一堆无效变量名称,即您使用myCar.'+ i 创建的变量名称。这根本不会为您的对象分配属性。但是你的错误的原因是myCar 是一个局部变量,而不是一个全局变量。这实际上只是试图理解这些概念的一种非常混乱的方式
  • " 我有兴趣追求它,以便更好地了解对象创建和 globals()[] " 它们完全不相关。理解这一点非常重要。 globals() 只会检索全局命名空间,其中包含模块的有效全局变量。 变量不是对象。变量引用对象。

标签: python class object globals


【解决方案1】:

有两种方法可以查看全局命名空间。一,它是变量的集合(与值相关联的标识符);二、是模块属性的集合(名字可以是任意字符串)。

globals()['myCar.make'] = 'Toyota' 不会创建变量,因为myCar.make 不是有效标识符。不过,它确实创建了一个模块属性,可以使用 getattr 访问。

>>> globals()['myCar.make'] = 'Toyota'
>>> import sys
>>> getattr(sys.modules['__main__'], 'myCar.make')
'Toyota'

分配没有设置myCar 引用的对象的make 属性,因为myCar.make = ...不是对名称的分配。它是myCar.__setattr__('make', 'Toyota') 的简写形式,或另一种形式setattr(myCar, 'make', 'Toyota')。如果你想动态创建属性,你可以这样做

name = 'myCar'
attr = 'make'
value = 'Toyota'

setattr(globals()[name], attr, value)

但是,如果您发现自己编写的代码看起来像这样,则几乎可以肯定您做错了什么。如果您需要将变量名称作为程序数据的一部分,那么您应该使用显式的dict,而不是全局命名空间。

【讨论】:

    【解决方案2】:

    您尝试定义类的方式没有意义。试试这个:

    class Car:
        def __init__(self, make, model, type, year):
            self.make = make
            self.model = model
            self.type = type
            self.year = year
    
    myCar = Car('Toyota', 'Prius', 'Sedan', 2010)
    print(myCar)
    print(myCar.make)
    print(myCar.model)
    print(myCar.type)
    print(myCar.year)
    

    请注意,只有一个顶级变量(myCar),各个值都是myCar 引用的Car 对象的属性。您的方法不起作用,因为您将 myCar.make 之类的表达式视为变量,这是无效的。

    【讨论】:

      猜你喜欢
      • 2012-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多