Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.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中返回实例化器吗?_Python_Oop - Fatal编程技术网

可以在Python中返回实例化器吗?

可以在Python中返回实例化器吗?,python,oop,Python,Oop,我知道这不是适当的封装,但出于兴趣 给定一个实例化子对象的父类,是否可以从子类中返回实例化它的父对象?如果没有,我很好奇,有任何语言支持这个吗?要回答这个问题,没有,子实例不可能知道任何包含对它的引用的类。处理此问题的常用方法是: class Parent(): def __init__(self): self.child = Child() class Child(): def __init__(self): # get Parent instance sel

我知道这不是适当的封装,但出于兴趣


给定一个实例化子对象的父类,是否可以从子类中返回实例化它的父对象?如果没有,我很好奇,有任何语言支持这个吗?

要回答这个问题,没有,子实例不可能知道任何包含对它的引用的类。处理此问题的常用方法是:

class Parent():
  def __init__(self):
    self.child = Child()

class Child():
  def __init__(self):
    # get Parent instance
    self.parent = self.Instantiator()
1当然,这不是严格意义上的事实。正如另一位评论员所指出的,您可以从uuu init_uuu方法中执行的代码中提取堆栈帧,并在当前执行的帧之前检查f_locals字典中的自变量。但这很复杂,而且容易出错。非常不受赞扬

2根据程序的具体需要,处理此问题的更好方法可能是要求家长将自己传递给孩子,如下所示:

class Parent(object):
    def __init__(self):
        self.child = Child()
        self.child._parent = self

要回答这个问题,不,子实例不可能知道任何包含对它的引用的类。处理此问题的常用方法是:

class Parent():
  def __init__(self):
    self.child = Child()

class Child():
  def __init__(self):
    # get Parent instance
    self.parent = self.Instantiator()
1当然,这不是严格意义上的事实。正如另一位评论员所指出的,您可以从uuu init_uuu方法中执行的代码中提取堆栈帧,并在当前执行的帧之前检查f_locals字典中的自变量。但这很复杂,而且容易出错。非常不受赞扬

2根据程序的具体需要,处理此问题的更好方法可能是要求家长将自己传递给孩子,如下所示:

class Parent(object):
    def __init__(self):
        self.child = Child()
        self.child._parent = self
你可以试着使用这个模块,只是为了证明一点

**孩子们,不要在家里尝试,你们可以试着使用这个模块,只是为了证明一点


**不要在家里尝试,孩子们*

这可以在python中使用元类来完成。

这可以在python中使用元类来完成。

下面是一个基于Chris B.的一些建议的示例,以说明检查堆栈是多么可怕:

class Parent(object):
    def __init__(self):
        self.child = Child(self)

class Child(object):
    def __init__(self, parent):
        self._parent = parent

当然可以,但千万不要尝试将其重构为单独的方法,或从中创建基类。

以下是一个基于Chris B.的一些建议的示例,说明检查堆栈是多么糟糕:

class Parent(object):
    def __init__(self):
        self.child = Child(self)

class Child(object):
    def __init__(self, parent):
        self._parent = parent

当然可以,但千万不要试图将其重构为单独的方法,或从中创建基类。

这里有一个相当简单的元类解决方案:

import sys

class Child(object):
    def __init__(self):
        # To get the parent:
        #  1. Get our current stack frame
        #  2. Go back one level to our caller (the Parent() constructor).
        #  3. Grab it's locals dictionary
        #  4. Fetch the self instance.
        #  5. Assign it to our parent property.
        self.parent = sys._getframe().f_back.f_locals['self']

class Parent(object):
    def __init__(self):
        self.child = Child()

if __name__ == '__main__':
    p = Parent()
    assert(id(p) == id(p.child.parent))
根据平台的不同,典型的输出如下

import functools

class MetaTrackinits(type):

  being_inited = []

  def __new__(cls, n, b, d):
    clob = type.__new__(cls, n, b, d)

    theinit = getattr(clob, '__init__')
    @functools.wraps(theinit)
    def __init__(self, *a, **k):
      MetaTrackinits.being_inited.append(self)
      try: theinit(self, *a, **k)
      finally: MetaTrackinits.being_inited.pop()
    setattr(clob, '__init__', __init__)

    def Instantiator(self, where=-2):
      return MetaTrackinits.being_inited[where]
    setattr(clob, 'Instantiator', Instantiator)

    return clob

__metaclass__ = MetaTrackinits


class Parent():
  def __init__(self):
    self.child = Child()

class Child():
  def __init__(self):
    self.parent = self.Instantiator()


p = Parent()
print p
print p.child.parent
在2.6和更高版本中,使用类装饰器可以获得类似的效果,但是所有需要父类和子类功能的类都必须显式装饰-在这里,它们只需要具有相同的元类,由于模块全局元类设置习惯用法以及元类(不同于类装饰)也被继承的事实,这可能会减少干扰


事实上,这是非常简单的,我会考虑允许它在生产代码中,如果需要那个神奇的实例化方法有一个被证明的商业基础,我永远不会允许,在生产代码中,黑客是基于走栈帧!顺便说一句,允许的部分来自强制性代码审查的最佳实践:没有审查者的一致意见,代码更改不会进入代码库的主干-这就是典型的开源项目的工作方式,也是我们在我的雇主总是如何操作的。

这里有一个合理简单的元类解决方案:

import sys

class Child(object):
    def __init__(self):
        # To get the parent:
        #  1. Get our current stack frame
        #  2. Go back one level to our caller (the Parent() constructor).
        #  3. Grab it's locals dictionary
        #  4. Fetch the self instance.
        #  5. Assign it to our parent property.
        self.parent = sys._getframe().f_back.f_locals['self']

class Parent(object):
    def __init__(self):
        self.child = Child()

if __name__ == '__main__':
    p = Parent()
    assert(id(p) == id(p.child.parent))
根据平台的不同,典型的输出如下

import functools

class MetaTrackinits(type):

  being_inited = []

  def __new__(cls, n, b, d):
    clob = type.__new__(cls, n, b, d)

    theinit = getattr(clob, '__init__')
    @functools.wraps(theinit)
    def __init__(self, *a, **k):
      MetaTrackinits.being_inited.append(self)
      try: theinit(self, *a, **k)
      finally: MetaTrackinits.being_inited.pop()
    setattr(clob, '__init__', __init__)

    def Instantiator(self, where=-2):
      return MetaTrackinits.being_inited[where]
    setattr(clob, 'Instantiator', Instantiator)

    return clob

__metaclass__ = MetaTrackinits


class Parent():
  def __init__(self):
    self.child = Child()

class Child():
  def __init__(self):
    self.parent = self.Instantiator()


p = Parent()
print p
print p.child.parent
在2.6和更高版本中,使用类装饰器可以获得类似的效果,但是所有需要父类和子类功能的类都必须显式装饰-在这里,它们只需要具有相同的元类,由于模块全局元类设置习惯用法以及元类(不同于类装饰)也被继承的事实,这可能会减少干扰


事实上,这是非常简单的,我会考虑允许它在生产代码中,如果需要那个神奇的实例化方法有一个被证明的商业基础,我永远不会允许,在生产代码中,黑客是基于走栈帧!顺便说一句,允许的部分来自强制性代码审查的最佳实践:如果没有审查人员的一致意见,代码更改不会进入代码库的主干-这就是典型的开源项目的工作方式,也是我们在我的雇主的工作方式。

取决于具体情况,元类有其用途。我认为,当需要对一些非python组件进行动态绑定时,这种情况就会出现。顺便说一句,python的基本对象是用元类完成的,除非我弄错了。Python有一个具有不同行为的遗留“object”类,这就是为什么我们被鼓励显式地从object继承
对那些使用回溯模块的元类进行回溯。根据情况,元类有其用途。我认为,当需要对一些非python组件进行动态绑定时,这种情况就会出现。顺便说一句,python的基本对象是用元类完成的,除非我弄错了。Python有一个具有不同行为的遗留“object”类,这就是为什么我们被鼓励显式地从object继承,与使用回溯模块的攻击相比,我更喜欢元类攻击。如果有人在不同的线程中创建两个完全独立的父实例,并且其中一个子实例的父线程来自另一个线程,或者甚至有另一个子线程作为父线程,那将是一件非常有趣的事情。@Duncan,如果您需要threadsafe版本,例如,您可以将threading.RLock添加到MetaTrackinits,并使用MetaTrackinits.thatlock:围绕嵌套的uuu init uuuu添加块-这不是火箭科学。鉴于CPython当前的线程限制,我们不太使用线程,因此一般规则是,默认情况下,功能不需要线程安全,除非明确记录为线程安全。@Chris,听起来像是不熟悉自定义元类的人说的话,这是一种非常可靠的技术,当reqs使其合适时,而且绝非聪明,尤其是这个词在Python社区中的负面含义。批评要求本身是有效的,但这应该意味着对问题的评论和否决票,而不是在这里;-,但是,批评满足这些要求的最佳方式,如我所说的,如果它们是一种经验证的业务需求,那当然是愚蠢的,否决票只会损害你的代表,因为我每天都会让代表出局;-@Chris感叹道,您当然应该对那些您希望重用和扩展其功能的类进行子类化,而不是其他类。如果您想重用和扩展父级或子级的确切功能,那么对它们进行子类化是非常好的。如果您想重用和扩展类X的功能,而不是仅仅是实例化器方法和对它的支持,那么您应该从该类继承,而不是从其他类继承。你有没有做过OOP,或者参加过OOP 101之类的课程…?@Chris,不一定-这取决于避免通过母公司是否是一项经验证的业务要求,正如我反复说过的那样。如果这一部分规范是一个经过验证的商业需求,那么这就是实现它的方法-它不聪明,也不复杂,也不脆弱我没有看到你发布任何替代方案来实现该规范-只针对该规范,而不是针对提出该规范的一方,Q,但只有在规范已修复的情况下,才针对我,然后等等。如果有人在不同的线程中创建两个完全独立的父实例,并且其中一个子实例的父实例来自另一个线程,或者甚至可能有另一个子实例作为父实例,这将是一件有趣的事情。@Duncan,如果您需要threadsafe版本,例如,您可以将threading.RLock添加到MetaTrackinits,并使用MetaTrackinits.thatlock:围绕嵌套的uuu init uuuu添加块-这不是火箭科学。鉴于CPython当前的线程限制,我们不太使用线程,因此一般规则是,默认情况下,功能不需要线程安全,除非明确记录为线程安全。@Chris,听起来像是不熟悉自定义元类的人说的话,这是一种非常可靠的技术,当reqs使其合适时,而且绝非聪明,尤其是这个词在Python社区中的负面含义。批评要求本身是有效的,但这应该意味着对问题的评论和否决票,而不是在这里;-,但是,批评满足这些要求的最佳方式,如我所说的,如果它们是一种经验证的业务需求,那当然是愚蠢的,否决票只会损害你的代表,因为我每天都会让代表出局;-@Chris感叹道,您当然应该对那些您希望重用和扩展其功能的类进行子类化,而不是其他类。如果您想重用和扩展父级或子级的确切功能,那么对它们进行子类化是非常好的。如果您想重用和扩展类X的功能,而不是仅仅是实例化器方法和对它的支持,那么您应该从该类继承,而不是从其他类继承。你有没有做过OOP,或者参加过OOP 101之类的课程…?@Chris,不一定-这取决于避免通过母公司是否是一项经验证的业务要求,正如我反复说过的那样。如果这部分规范是一个经过验证的商业需求,那么这就是实现它的方法——它不聪明,也不复杂,也不脆弱——我没有看到你发布任何替代方案来实现该规范——只针对该规范,而不是针对提出该规范的一方,Q,但只有在规范已修复的情况下,才针对我,等等。