如何使用属性简化此代码?

时间:2017-08-30 21:09:14

标签: python python-3.x properties

我阅读了文档,但不确定如何使用Python属性简化以下代码:

envelopesApi.GetDocument(accountId, envelopeID, "combined")

3 个答案:

答案 0 :(得分:3)

您可以覆盖使用obj.prop访问媒体资源时调用的__getattr____setattr__

class PatientRecordJson:
    properties = ['raw_data', 'data_type', 'type_of_record', 'npi']

    def __init__(self):
        self.json = {}

    def __getattr__(self, name):
        if name in PatientRecordJson.properties:
            return self.json.get(name)

        return super().__getattr__(name)

    def __setattr__(self, name, value):
        if name in PatientRecordJson.properties:
            self.json[name] = value

        return super().__setattr__(name, value)

用法示例:

pr = PatientRecordJson()
pr.raw_data              #=> None
pr.raw_data = 'raw data'
pr.raw_data              #=> 'raw data'
pr.json                  #=> {'raw_data': 'raw data'}
pr.z                     #=> AttributeError
pr.z = 2
pr.z                     #=> 2
pr.json                  #=> {'raw_data': 'raw data'}

注意:您已在课程中定义了json,如果您希望它是实例变量,请在self的{​​{1}}上创建它。

答案 1 :(得分:1)

如果您只是学习Python,这可能过于先进 - 但是通过使用它,您可以通过使用元类(其实例为其他类的类)在很大程度上自动化创建任意数量的类的过程。 / p>

虽然这样做需要一些非平凡的代码,但它使得定义目标类非常简单。另外,作为奖励,我添加了可选的类型检查。

def typed_property(field_name, expected_type=None):
    """ Helper function which creates and returns a property with the given
        name with optional type-checking. Each property retrieves or stores
        values from/to an instance-defined "json" dictionary attribute.
    """
    @property
    def prop(self):
        return self.json[field_name]

    @prop.setter
    def prop(self, value):
        if expected_type and not isinstance(value, expected_type):
            raise TypeError('Only {} values may be assigned to {}'.format(
                                expected_type.__name__, field_name))
        self.json[field_name] = value

    return prop


class PatientRecordMeta(type):
    """ Metaclass to define properties based on a class-level defined "fields"
        dictionary.
    """
    def __new__(metaclass, classname, bases, classdict):
        cls = super().__new__(metaclass, classname, bases, classdict)
        fields = classdict.get('fields')
        if not fields or not isinstance(fields, dict):
            raise TypeError('Class {} did not define required "fields" '
                            'instance dictionary'.format(classname))

        # Create the properties.
        for field, expected_type in fields.items():
            setattr(cls, field, typed_property(field, expected_type))

        return cls

定义的元类使得创建具有所需属性的类非常容易:

class PatientRecordJson(metaclass=PatientRecordMeta):
    fields = {'raw_data': str,
              'data_type': str,
              'type_of_record': str,
              'npi': int}  # Note changed to "int" to test type-checking,

    def __init__(self):
        self.json = {}  # define required instance attribute

    # Other methods could be defined here, too, if desired.
    # ...


patient_rec = PatientRecordJson()

patient_rec.raw_data = 'something'
patient_rec.bogus = 'something else'  # OK, but not saved in "self.json" dict.

try:
    patient_rec.npi = 'spam'  # -> Should cause a TypeError
except TypeError:
    pass  # expected TypeError occurred
else:
    print('Error: a TypeError did not occur as expected')

patient_rec.npi = 42  # Integer value is OK.

patient_rec.json['raw_data'] = 'eggs'  # can still do this
print(patient_rec.raw_data)  # -> eggs
print(patient_rec.npi)  # -> 42
print(patient_rec.json)  # -> {'raw_data': 'something', 'npi': 42}

答案 2 :(得分:0)

您可以使用__getattr____setattr__将动态字段视为对象本身的属性,而不是内部json对象的属性。

class PatientRecordJson:
    def __init__(self):
        self.fields = ['raw_data', 'data_type', 'type_of_record', 'npi']
        self.json = {}

    def __getattr__(self, key):
        if key not in self.fields:
            raise AttributeError
        return self.json.get(key, None)

    def __setattr__(self, key, data):
        if key not in self.fields
            raise AttributeError
        self.json[key] = data

上面的示例将允许您访问类似的属性。

patient = PatientRecordJson()
patient.data_type = 'something'
patient.npi = 12345
patient.raw_data = 'whatever you want here'
print(patient.data_type) #  'something'
print(patient.doesntexist) #  AttributeError
patient.notinfields = True #  AttributeError