Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

Python中的protected和private



Python中并没有public、protected、private这三个关键词的定义,但python中仍存在public、protected、private的概念。

Python中通过下划线来区分这三类,并限制了相关的变量和方法的继承和使用。(但我们仍然有办法访问到)

简单来说,无下划线的则是public,有一个下划线开头的则是protected,有两个下划线开头的则是private,注意前后都有下划线的是内置的比如__init__. 其实加了下划线的就是一个约定,告诉别人不要随意调用。

public是对外开放的,protected是只有自己和子类能用的,private则是只有自己能用的。

我们先看看变量和方法。先创建一个文件protect_private.py:

public_value = "public_value"
_protect_value = "protect_value"
__private_value = "private_value"


def public_method():
    return "public"


def _protect_method():
    return "protect"


def __private_method():
    return "private"

然后在命令行试试:

>>> from protect_private import *
>>> public_value
'public_value'
>>> _protect_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_protect_value' is not defined
>>> __private_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '__private_value' is not defined
>>> public_method()
'public'
>>> _protect_method()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_protect_method' is not defined
>>> __private_method()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '__private_method' is not defined

我们可以看到,在import后,public的可以调用,但是protect和private的无法被调用。这三个变量和三个方法只能在原文件中才能都被调用。

接下来我们再看看Class中和被import后的情况。修改文件内容为如下:

class Person:

    def __init__(self):
        self.name = "Bob"
        self._gender = "male"
        self.__age = "18"

    def show_name(self):
        return self.name

    def _show_name_protect(self):
        return self.name

    def __show_name_private(self):
        return self.name

    @property
    def info_name(self):
        return self.name

    @info_name.setter
    def info_name(self, value):
        self.name = value

    @property
    def info_gender(self):
        return self._gender

    @info_gender.setter
    def info_gender(self, value):
        self._gender = value

    @property
    def info_age(self):
        return self.__age

    @info_age.setter
    def info_age(self, value):
        self.__age = value


class Child(Person):

    def show_parent_name(self):
        return self.name

    def show_parent_gender(self):
        return self._gender

    def show_parent_age(self):
        return self.__age

    def call_parent_public_method(self):
        return self.show_name()

    def call_parent_protect_method(self):
        return self._show_name_protect()

    def call_parent_private_method(self):
        return self.__show_name_private()

先试试Person中的变量:

>>> from protect_private import *
>>> p = Person()
>>> p.name
'Bob'
>>> p._gender
'male'
>>> p.__age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute '__age'

我们看到初始化Person后,public和protected都可以被访问,但private则不可被访问。其实这只是不允许直接用变量名访问,我们仍然可以用p._Person__age来获得,这个叫名称改写。我们可以用dir来看看Person这个类有什么属性。

>>> dir(p)
['_Person__age', '_Person__show_name_private', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_gender', '_show_name_protect', 'info_age', 'info_gender', 'info_name', 'name', 'show_name']
>>> p._Person__age
'18'

接着试试Person中的方法:

>>> p.show_name()
'Bob'
>>> p._show_name_protect()
'Bob'
>>> p.__show_name_private()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute '__show_name_private'

类中的方法也是一样,public和protected都可以被访问,但private则不可被访问。

private的方法也是一样有名称改写,可以通过p._Person__show_name_private()来访问。

>>> p._Person__show_name_private()
'Bob'

除此之外,我们可以自定义一个方法来返回protected和private的变量和方法,也可以用装饰器@property和@setter,这里就需要程序员自己决定哪些能被访问不要随意修改到重要的值。

>>> p.info_age
'18'
>>> p.info_age = 19
>>> p.info_age
19

接下来再看看子类:

>>> c = Child()
>>> c.show_parent_name()
'Bob'
>>> c.show_parent_gender()
'male'
>>> c.show_parent_age()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "./protect_private.py", line 67, in show_parent_age
    return self.__age
AttributeError: 'Child' object has no attribute '_Child__age'
>>> c.call_parent_public_method()
'Bob'
>>> c.call_parent_protect_method()
'Bob'
>>> c.call_parent_private_method()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "./protect_private.py", line 76, in call_parent_private_method
    return self.__show_name_private()
AttributeError: 'Child' object has no attribute '_Child__show_name_private'

由此也看到protected能被子类使用,但private则不能被子类使用。

下一篇:  阿里云设置二级域名并更新nginx配置
上一篇:  Python加Selenium自动化测试知乎网站(三)页面对象模式

共有0条评论

添加评论

暂无评论