如何确保在第一次调用另一个类函数之前不会调用类函数?

时间:2014-01-15 15:22:22

标签: python python-2.7

我有一个创建一些数据字段的类对象:

class DataFields(object):

   _fields_ = ['field_1', 'field_2', 'data_length']

    def __init__(self, data=None):
        if data != None:
           self.create_fields(data)

    def create_fields(self, data):
        i = 0
        for field in self._fields_:
            setattr(self, field, data[i])
            i += 1

    def get_datalength(self):
        return self.data_length

除非已创建get_datalength()字段(即,除非data_length函数已被调用一次),否则无法调用create_fields()函数的最佳方法是什么? 。

我考虑使用在create_fields中初始化的变量,并在get_datalength()函数中try-exceptget_datalength()中进行检查。什么是最Pythonic(或最好的)方式?

4 个答案:

答案 0 :(得分:4)

我认为最狡猾的方式是抛出异常:

def get_datalength(self):
    try:
        return self.data_length
    except AttributeError:
        raise AttributeError("No length call create_fields first")

原因很简单:无法阻止用户在对象上调用此函数。用户将获得AttributeError并且无法理解发生了什么,或者您提供了自己的错误类或至少错误消息。

顺便说一句: 它不是pythonic创建getter方法(没有'私人成员'这样的东西) 如果您需要对返回的值执行较小的操作,请查看@property装饰器

@property
def datalength(self):
   return do_some_stuff(self.data_length)

答案 1 :(得分:1)

使用默认值getattr,如果实例中没有None属性,则可以返回data_length或任何值:

def get_datalength(self):
    return getattr(self, 'data_length', None)

答案 2 :(得分:0)

使用异常可能是您正在进行的操作的最佳方式,但如果您将从交互式控制台使用此对象,则可能有用的替代方法:

def fn2(self):
    print("this is fn2")

class test:
    def fn1(self):
        print("this is fn1")
        self.fn2 = fn2
    def fn2(self):  # omit this if you want fn2 to only exist after fn1 is called
        print("Please call fn1 first")

我不建议每天使用它,但在某些情况下它可能很有用。如果省略在类中定义fn2,则方法fn2将仅在调用fn1后出现。为了便于代码维护,您可以执行相同的操作:

class test:
    def fn1(self):
        print("this is fn1")
        self.fn2 = self._fn2
    def _fn2(self):
        print("this is fn2")
    def fn2(self):  # omit this if you want fn2 to only exist after fn1 is called
        print("Please call fn1 first")

如果要在要导入的模块中使用它,那么您应该引发异常或返回有效值,就像其他答案所建议的那样。

答案 3 :(得分:0)

这可以通过将字典作为类变量,方法名称作为键来解决。

called['method1'] 
called['method2']
called['method3']
...

在该方法调用中设置密钥

class SomeClass(obj):
    def method1():
        called['method1'] = 1
    def method2():
        if method1 in called:
            # continue