zoukankan      html  css  js  c++  java
  • 为什么不需要为Python对象添加 getter 和 setter

    Getter 和 setter在java中被广泛使用。一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和setter函数以供外部使用。 这样做的好处是属性的具体实现被隐藏,当未来需要修改时,只需要修改getter 和 setter即可,而不用修改代码中所有引用这个属性的地方。可能做的修改为:

    • 在获取或设置属性时打一条日志
    • 设置属性时,对值对进检查
    • 设置发生时, 修改设置的值
    • 获取属性时,动态地计算值

    可谓是好处多多,getter和setter为变量访问提供了灵活的方式。

    但python中情况却不同,因为对象属性访问的机制不同。java中需要为变量写getter和setter的原因为:当我们写这样的表达式 person.name 来获取一个 person 对象的 name 属性时,这个表达式的意义是固定的,它就是获取这个属性,而不可能触发一个函数的调用。但对于python, 这个表达式即可能是直接获取一个属性,也可能会调用一个函数。这取决 Person 类的实现方式。也就是说,python的对象属性访问的语法,天然就提供了getter和setter的功能。

    由于这个区别,我们没有必要在python中为每个对象的属性写getter和setter。最开始时,我们总是将属性作为一个直接可访问的属性。当后续需要对这个属性的访问进行一些控制时,我们可以将其修改为函数触发式属性。在修改前后,调用这个对象属性的代码不用修改,因为还是使用相同的语法来访问这个属性。

    可以使用@property 装饰器将一个直接访问的属性转变为函数触发式属性。如下所示,使用@property前的代码为

    class Person:
        def __init__(self, name):
            self.name = name
    
    person = Person("Tom")
    print(person.name)

    代码的输出为:

    Tom

    此时为直接访问 name 这个属性。当我们需要确保 name 是一个字符串时,可以使用 @property 装饰器将属性转变为一个函数调用,如下所示。

    class Person:
        def __init__(self, name):
            self.name = name
    
        @property
        def name(self):
            print("get name called")
            return self._name
    
        @name.setter
        def name(self, name):
            print("set name called")
            if not isinstance(name, str):
                raise TypeError("Expected a string")
            self._name = name
    
    person = Person("Tom")
    print(person.name)

    代码的输出为:

    set name called
    get name called
    Tom

    可以看出

    • 在创建Person对象时(代码的倒数第二行), 用于set name的函数被调用。这个函数会检查输入是否为一个字符串,如不是则raise一个TypeError
    • 在获取属性时(代码的最后一行),用于get name的函数被调用
    • 在修改前后,使用Person类的代码完全相同

    总结

    Python中对象访问的语法即可能是直接访问这个属性,也可能是调用一个函数,这取决于类的实现方式。我们可以在不修改调用者代码的前提下,轻松切换这两种方式。可见python原生就提供了添加额外getter和setter所带来的好处。因此没有必要一开始就为对象属性编写getter和setter函数,而是在需要时切换到函数调用式属性。

     
  • 相关阅读:
    jstl 部分标签
    Maven pom.xml 元素配置说明(一)
    spring 参数绑定
    mysql 索引
    ArrayList和HashSet的Contains()方法(转)
    每日记载内容总结44
    剑指offer42:不用加减乘除做加法
    动态规划常见题型
    华为机试-统计每个月兔子的总数
    华为机试-字符串合并处理
  • 原文地址:https://www.cnblogs.com/astropeak/p/7229508.html
Copyright © 2011-2022 走看看