Python面向对象编程中如何实现访问控制?

写了一篇关于 Python 访问控制的文章,请各位大佬鉴定一下。
https://juejin.im/post/5ac18d08f265da237b223d1a
Python面向对象编程中如何实现访问控制?

24 回复

学 py 的时候看过这段,严格来说 py 是没有私有的,通过下划线其实是提醒后来人谨慎使用该变量。


在Python里实现访问控制,主要靠命名约定和属性装饰器。Python没有Java那种严格的private、protected关键字,但有一套大家遵守的规则。

1. 单下划线 _:约定上的“保护”成员 加个单下划线开头,比如 _protected_var。这只是个约定,告诉其他程序员:“这是内部用的,别直接从外面乱动”。但解释器不会阻止你访问。

class MyClass:
    def __init__(self):
        self.public = "随便访问"
        self._protected = "建议别直接动我"
        
obj = MyClass()
print(obj.public)        # 可以
print(obj._protected)    # 也可以,但不太讲究

2. 双下划线 __:名称改写(Name Mangling) 用双下划线开头,比如 __private_var。Python解释器会把这个属性名改成 _类名__变量名 的形式。这算是某种程度的“私有化”,主要为了防止子类意外重写父类属性。

class MyClass:
    def __init__(self):
        self.__private = "我真的不想被直接改"
        
    def get_private(self):
        return self.__private
        
obj = MyClass()
# print(obj.__private)  # 直接这么访问会报错:AttributeError
print(obj.get_private()) # 通过公有方法访问,可以
print(obj._MyClass__private) # 知道改名规则后硬要访问,也行,但非常不推荐

3. 属性装饰器 @property:控制访问和修改 这是最Pythonic、最常用的方式。用 @property 把一个方法变成“属性”来读,用 @属性名.setter 来控制写操作,用 @属性名.deleter 控制删除。你可以在这些方法里加任何检查逻辑。

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age
        
    @property
    def age(self):
        """获取年龄"""
        return self._age
        
    @age.setter
    def age(self, value):
        """设置年龄,加个合法性检查"""
        if not isinstance(value, int):
            raise TypeError("年龄得是整数")
        if value < 0 or value > 150:
            raise ValueError("年龄得现实点")
        self._age = value
        
    @age.deleter
    def age(self):
        """不让删年龄属性"""
        raise AttributeError("年龄这属性可不能删")
        
p = Person("小明", 25)
print(p.age)    # 像属性一样读,实际调用的是 getter 方法
p.age = 30      # 像属性一样写,实际调用的是 setter 方法
# p.age = -5    # 会触发 ValueError
# del p.age     # 会触发 AttributeError

总结一下:

  • 想暗示“内部使用”:用单下划线 _
  • 想避免子类属性冲突:用双下划线 __ 触发名称改写。
  • 想精细控制属性的读、写、删行为,并加入逻辑:用 @property 装饰器。

核心建议: 多用 @property,它是Python实现封装和访问控制的首选工具。

楼主要想搞个大新闻,还是找点有深度的主题吧!这东西任何一本入门书都有讲解

讲 py3 源码才能在 v 站立足

标题赞一个

谢谢楼主不辞辛苦跑来告诉大家母鸡是会下蛋的。
只是哲学不同,我们都认为自己是成年人。

感谢 + 没有帮助(

这篇真的有点水了… python 不了解这个特性可以说是完全不会 python 吧…

真正访问控制应该是 吧

快出去走道里看看 看到墙上有火警报警按钮没,会不会误触?非要按能不能按下去?但是你应不应该按?

基础文章,还不错 ; ) 可以看看描述符之类

只是哲学不同,我们都认为自己是成年人,这句话什么意思?

写得可以,之前一直把 python 当脚本来写的,面向对象没用过

everything is available at runtime

正确的访问控制应该使用 getattr setattr

自定义的方法或变量在任何时候都不应该使用 foo 的形式。js 社区前短时间好像在争执 Array.prototype.flatten 的方法问题,因为和有个库定义了 flatten,js 如果加入这个的话会冲突。所以有人提议我们用 smoosh (笑)

Python 就没有这个问题,只要大家老老实实把魔术方法保留给 Python 语言。

和 9 楼一个意思。

配图用个 C++//

。。。。。。。。。。。任何一本 python 入门数都会讲的东西

如果对这个都不了解换我我可能直接拒了

1、_xxx 不能用于’ from module import *’ 以单下划线开头的表示的是 protected 类型的变量。即保护类型只能允许其本身与子类进行访问。
2、__xxx 双下划线的表示的是私有类型的变量。只能是允许这个类本身进行访问了。连子类也不可以

“”“是一种约定的规范,而不是语言层面真的实现了访问控制…”"" lz 搞笑吗

这句话有什么问题吗?

这怕是不能谈笑风生吧

水到不行

回到顶部