【问题标题】:Check if method already is in instance in object?检查方法是否已经存在于对象中?
【发布时间】:2017-02-24 05:08:46
【问题描述】:

我正在尝试查看我的对象是否已经存在某个属性的实例。正如您在下面看到的,如果我的Dog 对象具有某个属性,我想做一些事情,通过do_something_if_has_aged 方法。如何检查某个属性是否已经声明?通常你会用这样的东西来检查是否存在,它会返回False:

obj = None
if obj:
    print(True)
else:
    print(False)

这是我的最小可重现示例:

>>> class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def add_years(self, years):
        self.age += years
        self.has_aged = True
    def do_something_if_has_aged(self):
        if self.has_aged:
            print("The dog has aged and is %d years closer to death" % self.years)
        else:
            print("The dog hasn't aged, apparently.")


>>> dog = Dog('Spot', 3)
>>> dog.age
3
>>> dog.do_something_if_has_aged()
Traceback (most recent call last):
  File "<pyshell#193>", line 1, in <module>
    dog.do_something_if_has_aged()
  File "<pyshell#190>", line 9, in do_something_if_has_aged
    if not self.has_aged:
AttributeError: 'Dog' object has no attribute 'has_aged'
>>> dog.add_years(1)
>>> dog.age
4
>>> dog.do_something_if_has_aged()
The dog hasn't aged, apparently.

不过,很明显这只狗已经变老了

如果标题没有反映我在下面试图传达的内容,我深表歉意;我是 OOP 的新手。

【问题讨论】:

  • 你的情况是错误的:你应该这样做if self.has_aged

标签: python class oop attributes instance


【解决方案1】:

看起来您正在寻找hasattr 内置函数:

>>> class Dog(object):
...     pass
...
>>> a = Dog()
>>> hasattr(a, 'age')
False
>>> a.age = 7
>>> hasattr(a, 'age')
True

在你的情况下,你可以修改如下:

def do_something_if_has_aged(self):
    if hasattr(self, 'has_aged'):
        pass # do your logic

【讨论】:

    【解决方案2】:

    而不是测试属性,在类上设置一个默认值;如果缺少实例属性,Python 会寻找类属性:

    class Dog:
        has_aged = False  # default for all instances
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def add_years(self, years):
            self.age += years
            self.has_aged = True  # sets an instance attribute
        def do_something_if_has_aged(self):
            if self.has_aged:
                print("The dog has aged and is %d years closer to death" % self.years)
            else:
                print("The dog hasn't aged, apparently.")
    

    (请注意,我必须反转您的测试,如果 self.has_agedtrue 您想进入第一个分支,而不是相反)。

    或者你可以在__init__中为属性设置一个默认值:

    class Dog:
        def __init__(self, name, age):
            self.name = name
            self.age = age
            self.has_aged = False
        def add_years(self, years):
            self.age += years
            self.has_aged = True
        def do_something_if_has_aged(self):
            if self.has_aged:
                print("The dog has aged and is %d years closer to death" % self.years)
            else:
                print("The dog hasn't aged, apparently.")
    

    您还可以使用hasattr() function 测试属性是否存在:

    def do_something_if_has_aged(self):
        if hasattr(self 'has_aged') and self.has_aged:
            print("The dog has aged and is %d years closer to death" % self.years)
        else:
            print("The dog hasn't aged, apparently.")
    

    或者通过使用带有默认值的getattr() function

    def do_something_if_has_aged(self):
        if not getattr(self 'has_aged', False):
            print("The dog has aged and is %d years closer to death" % self.years)
        else:
            print("The dog hasn't aged, apparently.")
    

    但是,动态测试属性不应该是您选择的第一个选项;拥有一个类默认值会更干净。

    【讨论】:

    • has_aged 作为类变量而不是实例变量(在__init__ 中定义)有什么优势?
    • @JosieThompson:变量只有一个副本(因此内存优势);当默认值可以存储在类中时,为什么要为所有实例赋予属性?
    【解决方案3】:

    我会重写 __init__ 方法以包含 self.has_aged = False 以避免进行检查:

    class Dog(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
            self.has_aged = False # Starting value so it is guaranteed to be defined (unless explicitly deleted).
    

    现在,你班上的其他人应该按照书面的方式工作。但是,如果你想查看一个对象是否已经定义了一个属性,你可以这样写:

    class Foo(object):
        def set_bar(self):
            self.bar = True # Define the attribute bar if it is not yet defined.
    
        def is_bar_set(self):
            return hasattr(self, 'bar')
    

    【讨论】:

      【解决方案4】:

      要检查使用 hasattr 是否完全没问题,但如果您正在寻找代码的快速修复方法,您可以事先将变量初始化为 false:

      class Dog:
        has_aged = False
      

      以及我认为应该逆转的修复您的状况:

      def do_something_if_has_aged(self):
        if self.has_aged:    # instead of not self.has_aged
          print("The dog has aged and is %d years closer to death" % self.years)
        else:
          print("The dog hasn't aged, apparently.")
      

      【讨论】:

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