Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用python';要正确地实例化嵌套类,请使用s\uu import\uu()和getattr()?_Python_Python Import_Instantiation_Inner Classes - Fatal编程技术网

如何使用python';要正确地实例化嵌套类,请使用s\uu import\uu()和getattr()?

如何使用python';要正确地实例化嵌套类,请使用s\uu import\uu()和getattr()?,python,python-import,instantiation,inner-classes,Python,Python Import,Instantiation,Inner Classes,我在模块xyz中有以下代码: Class Outer: Class Nested: pass 我可以成功地实例化Outer对象,如下所示 module = __import__("xyz", fromlist=['']) the_class = getattr(module, "Outer") instance = the_class() 但是,当我将“Outer”替换为“Outer.Nested”时,我得到: AttributeE

我在模块xyz中有以下代码:

Class Outer:
   Class Nested:
       pass
我可以成功地实例化
Outer
对象,如下所示

module = __import__("xyz", fromlist=[''])
the_class = getattr(module, "Outer")
instance = the_class()
但是,当我将
“Outer”
替换为
“Outer.Nested”
时,我得到:

AttributeError:模块“xyz”没有外部属性。嵌套的

如何才能做到这一点


我也许应该澄清一下,上面的代码用于实例化在运行时之前类型未知的类。显然,我不是在寻找
instance=Outer.Nested()

两种方法,假设您有一个表示属性访问的字符串和一个嵌套对象:

>>> from types import SimpleNamespace
>>> module = SimpleNamespace(foo=SimpleNamespace(bar=SimpleNamespace(baz='tada!')))
>>> module
namespace(foo=namespace(bar=namespace(baz='tada!')))
第一种方法是通过拆分并在循环中使用
getattr
(甚至,
reduce
!)自己解析字符串:

这相当于:

>>> result = module
>>> for attr in "foo.bar.baz".split("."):
...     result = getattr(result, attr)
...
>>> result
'tada!'
或者一次性使用内置的
functools.attrgetter
factory函数:

>>> import operator
>>> operator.attrgetter("foo.bar.baz")(module)
'tada!'

有两种方法可以做到这一点,假设您有一个表示属性访问的字符串和一个嵌套对象:

>>> from types import SimpleNamespace
>>> module = SimpleNamespace(foo=SimpleNamespace(bar=SimpleNamespace(baz='tada!')))
>>> module
namespace(foo=namespace(bar=namespace(baz='tada!')))
第一种方法是通过拆分并在循环中使用
getattr
(甚至,
reduce
!)自己解析字符串:

这相当于:

>>> result = module
>>> for attr in "foo.bar.baz".split("."):
...     result = getattr(result, attr)
...
>>> result
'tada!'
或者一次性使用内置的
functools.attrgetter
factory函数:

>>> import operator
>>> operator.attrgetter("foo.bar.baz")(module)
'tada!'

以@juanpa.arrivillaga的答案为基础(但解释原因):


类和模块在Python中被视为对象。因此,当您在模块中声明一个类时,该类是该模块的一个属性;当您声明内部类时,内部类是外部类的属性,而不是模块的属性。当您将
“Outer.Nested”
交给模块的
getattr
时,您需要模块的属性,因此属性的名称中有一个
。与属性的属性不完全相同。Python的解释器在解析时会执行“属性的属性”,因此您会感到困惑。

以@juanpa.arrivillaga的答案为基础(但解释原因):

类和模块在Python中被视为对象。因此,当您在模块中声明一个类时,该类是该模块的一个属性;当您声明内部类时,内部类是外部类的属性,而不是模块的属性。当您将
“Outer.Nested”
交给模块的
getattr
时,您需要模块的属性,因此属性的名称中有一个
。与属性的属性不完全相同。Python的解释器在解析时会执行“属性的属性”,因此您会感到困惑。

我也许应该澄清一下,上面的代码用于实例化在运行时之前类型未知的类。显然,我不是在寻找
instance=Outer.Nested()
。 您的意思是直到运行时才知道名称吗?Python中的所有类型都是在运行时确定的

如果是这样,您也可以做一个奇特但常见的技巧,调用方可以在运行时提交类型

#xyz.py
def get_实例(_类):
返回_类()
未知第三方
外部类别:
类嵌套:
通过
#main.py
从xyz导入获取_实例
导入未知的第三方
instance=get\u instance(未知的第三方\u.Outer.Nested)
您永远不需要知道要运行的代码要交给什么——这是由您的用户/客户在运行时决定的

研究Python使用
@
作为语法糖的原因,找出这一现象如此普遍的原因。

我也许应该澄清一下,上面的代码用于实例化在运行时之前类型未知的类。显然,我不是在寻找
instance=Outer.Nested()
。 您的意思是直到运行时才知道名称吗?Python中的所有类型都是在运行时确定的

如果是这样,您也可以做一个奇特但常见的技巧,调用方可以在运行时提交类型

#xyz.py
def get_实例(_类):
返回_类()
未知第三方
外部类别:
类嵌套:
通过
#main.py
从xyz导入获取_实例
导入未知的第三方
instance=get\u instance(未知的第三方\u.Outer.Nested)
您永远不需要知道要运行的代码要交给什么——这是由您的用户/客户在运行时决定的


研究Python使用
@
作为语法糖的原因,找出这一现象如此普遍的原因。

因此,只需应用
getattr
两次,类似于
outer,nested=“outer.nested”.split('.');klass=getattr(getattr(模块,外部),嵌套)
或者,使用将与嵌套属性一起工作的
操作符.attrgetter
access@juanpa. 没错!非常感谢。我刚刚用
get_class=operator.attrgetter('Outer.Nested')替换了
getattr
行;_class=get_class(模块)
非常有效。我觉得我应该投票,把你的答案标为正确答案。如果你想发布答案,就这样做。所以,只需应用两次
getattr
,比如
outer,nested=“outer.nested”。split('.');klass=getattr(getattr(模块,外部),嵌套)
或者,使用将与嵌套属性一起工作的
操作符.attrgetter
access@juanpa. 没错!非常感谢。我刚刚用
get_class=operator.attrgetter('Outer.Nested')替换了
getattr
行;_class=get_class(模块)
非常有效。我觉得我应该投票,把你的答案标为正确答案。如果你想在网站上发布答案,我会这样做。谢谢继续。谢谢