为什么属性引用与 Python 继承的行为如此相似?[重复]

2025-03-21 09:07:00
admin
原创
67
摘要:问题描述:以下内容看起来很奇怪..基本上,somedata 属性似乎在从继承的所有类之间共享the_base_class。class the_base_class: somedata = {} somedata['was_false_in_base'] = False class subc...

问题描述:

以下内容看起来很奇怪..基本上,somedata 属性似乎在从继承的所有类之间共享the_base_class

class the_base_class:
    somedata = {}
    somedata['was_false_in_base'] = False


class subclassthing(the_base_class):
    def __init__(self):
            print self.somedata


first = subclassthing()
{'was_false_in_base': False}
first.somedata['was_false_in_base'] = True
second = subclassthing()
{'was_false_in_base': True}
>>> del first
>>> del second
>>> third = subclassthing()
{'was_false_in_base': True}

self.somedata在函数中定义__init__显然是解决这个问题的正确方法(所以每个类都有自己的somedata字典) - 但是什么时候这种行为是可取的?


解决方案 1:

你是对的,somedata它是在类及其子类的所有实例之间共享的,因为它是在类定义时创建的。

somedata = {}
somedata['was_false_in_base'] = False

在定义类时执行,即解释器遇到class语句时执行 -而不是在创建实例时执行(请考虑 Java 中的静态初始化块)。如果类实例中不存在某个属性,则检查类对象是否存在该属性。

在类定义时,您可以运行任意代码,如下所示:

 import sys
 class Test(object):
     if sys.platform == "linux2":
         def hello(self):
              print "Hello Linux"
     else:
         def hello(self):
              print "Hello ~Linux"

在 Linux 系统上,Test().hello()将打印Hello Linux,在所有其他系统上,将打印其他字符串。

相比之下, 中的对象__init__是在实例时创建的,并且仅属于该实例(当它们被分配给时self):

class Test(object):
    def __init__(self):
        self.inst_var = [1, 2, 3]

在类对象上定义的对象(而不是实例)在许多情况下都很有用。例如,您可能希望缓存类的实例,以便可以共享具有相同成员值的实例(假设它们应该是不可变的):

class SomeClass(object):
    __instances__ = {}

    def __new__(cls, v1, v2, v3):
        try:
            return cls.__insts__[(v1, v2, v3)]
        except KeyError:
            return cls.__insts__.setdefault(
               (v1, v2, v3), 
               object.__new__(cls, v1, v2, v3))

大多数情况下,我将类主体中的数据与元类或通用工厂方法结合使用。

解决方案 2:

请注意,您所看到的部分行为是由于somedatadict而不是诸如 之类的简单数据类型bool

例如,看看这个行为不同(尽管非常相似)的不同例子:

class the_base_class:
    somedata = False

class subclassthing(the_base_class):
    def __init__(self):
        print self.somedata


>>> first = subclassthing()
False
>>> first.somedata = True
>>> print first.somedata
True
>>> second = subclassthing()
False
>>> print first.somedata
True
>>> del first
>>> del second
>>> third = subclassthing()
False

这个例子的行为与问题中给出的例子不同,原因是这里first.somedata被赋予了一个新值(对象True),而在第一个例子中,引用的 dict 对象first.somedata(以及其他子类实例)被修改了。

请参阅 Torsten Marek 对此答案的评论以获得进一步的说明。

解决方案 3:

我认为理解这一点的最简单方法(以便您可以预测行为)是认识到somedata如果您以这种方式定义它,您是该类的一个属性而不是该类的实例。

实际上始终只有一个,somedata因为在您的示例中,您没有分配给该名称,而是使用它来查找字典,然后为其分配一个项目(键、值)。这是一个陷阱,是 Python 解释器工作方式的结果,一开始可能会令人困惑。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用