与面试官谈笑风生 | Python面向对象之访问控制

转载 2018年04月16日 10:49:14

Python从设计之初就是一门面向对象的语言,面向对象思想的第一个要素就是封装。所谓封装,通俗的讲就是类中的属性和方法,分为公有和私有,公有可以被外界访问,私有不能被外界访问,这就是封装中最关键的概念——访问控制。

访问控制有三种级别:私有、受保护、公有

私有(Private):只有类自身可以访问 受保护(Protected):只有类自身和子类可以访问 公有(Public):任何类都可以访问

由于Python不像Java,有访问控制符(private / public / protected),所以Python的访问控制也是容易被应聘者忽视和搞错的。

公有(Public)

在Python的类中,默认情况下定义的属性都是公有的。

class Foo(object): bar = 123 def __init__(self, bob): self.bob = bob print(Foo.bar)  # 123 foo = Foo(456) print(foo.bob)  # 456

上面类Foo中的bar属性就是类属性,__init__方法中定义的bob是实例属性,barbob都是公有的属性,外部可以访问,分别print类中的bar和实例中的bob,输出了对应的值。

受保护(Protected)

在Python中定义一个受保护的属性,只需要在其名字前加一个下划线_,我们将Foo方法中的bobbar改为_bob_bar,他们就变成了受保护的属性了,代码如下:

class Foo(object): _bar = 123 def __init__(self, bob): self._bob = bob class Son(Foo): def print_bob(self): print(self._bob)  @classmethod def print_bar(cls): print(cls._bar) Son.print_bar()  # 123 son = Son(456) son.print_bob()  # 456

定义一个类Son继承自Foo,由于受保护的对象只能在类的内部和子类中被访问,不能直接调用print(Son._bar)print(son._bob)来输出这两个属性的值,所以定义了print_barprint_bob方法,实现在子类中输出,这段代码也正常的输出了_bar_bob的值。

接下来,试着反向验证一下,在类的外部,能不能访问其属性,将上面代码的输出部分修改如下:

print(Son._bar)  # 123 son = Son(456) print(son._bob)  # 456

(假装)惊讶的发现,竟然没有报错,也输出了正确的值。

Python中用加下划线来定义受保护变量,是一种约定的规范,而不是语言层面真的实现了访问控制,所以,我们定义的保护变量,依然可以在外部被访问到(这是个feature,不是bug)。

私有(private)

Python定义私有属性,需要在属性名前加两个下划线__,把上面的代码修改一下,运行一下会发现下面的代码中的任何一个print都会报错的。

class Foo(object): __bar = 123 def __init__(self, bob): self.__bob = bob class Son(Foo): def print_bob(self): print(self.__bob)  # Error  @classmethod def print_bar(cls): print(cls.__bar)  # Error print(Son.__bar)  # Error son = Son(456) print(son._bob)  # Error

深入一下——私有属性真的就访问不到了吗?

要了解私有属性是否真的访问不到,需要从Python是如何实现私有属性入手。CPython中,会把双下划线的属性变为_ClassName__PropertyName的形式,用代码演示一下:

class Foo(object): __bar = 123 print(Foo._Foo__bar)  # 123

运行一下可以知道,正常输出了__bar的值,但是不推荐这样去访问私有属性,因为不同的Python解释器对于私有属性的处理不一样。

特例

使用双下划线定义私有属性,有一种特殊情况,当属性后也有两个下划线的时候,这个属性会被Python解释器当做魔术方法,从而不做私有处理。

class Foo(object): __bar__ = 123 print(Foo.__bar__)  # 123

上面代码输出了123,证明Python解释器并没有把__bar__当做私有属性。当定义私有属性时,需要注意名字最后最多只能有一个下划线。

另一个特例

假如定义的属性名就叫__呢?不妨直接试一下:

class Foo(object): __ = 123 print(Foo.__)  # 123

可以发现名字叫__的属性也不会被认为是私有属性,名字是多个下划线的属性也不是私有属性(比如_______)。

函数的访问控制

前面主要介绍了属性的访问控制,在Python中函数是一等公民,所谓一等公民,就是函数可以像变量一样使用,所以函数的访问控制和属性一样,一样应用上面的规则。叉车配件

python面向对象

python的设计哲学便是一切皆对象,到这一部分,我们真正开始学习什么是面向对象的设计哲学,课程主要涉及类和面向对象的概念,类的三大特性:封装,继承,多态以及反射和class特性等,该章节是我们学习python的重中之重。
  • 2017年03月03日 17:35

php面向对象-一揽子方案

php面向对象-一揽子方案
  • gsdgsdfs
  • gsdgsdfs
  • 2017-05-24 07:04:26
  • 872

【面向对象】php新手之学习类与对象-访问控制

四、访问控制 对属性或方法的访问控制,是通过在前面添加关键字 public、protected 或 private 来实现的。由 public 所定义的类成员可以在任何地方被访问;由 prote...
  • yanhui_wei
  • yanhui_wei
  • 2012-11-27 10:37:13
  • 510

java 中访问控制 public、private 和 protected 介绍

Java的访问控制机制说明: 1.任何声明为public的内容可以被从任何地方访问。 2.被声明成private的成员不能被该类外看到。 3.如果一个成员不含有一个明确的访问说明,则它只对同包可见...
  • zkp0601
  • zkp0601
  • 2015-10-30 20:33:17
  • 554

bzoj3653: 谈笑风生

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3653 题意:中文题。 分析:很明显这题可以分为两种情况:(1)b是a的祖先,那么有min(...
  • Fsss_7
  • Fsss_7
  • 2016-04-06 22:36:49
  • 552

当面试官问:‘’谈一下你面向对象的理解‘’时,你该如何回答~~~

回答面试一定要有深度,让面试的大哥感觉你的水平有层次感面向对象编程,即OOP,是一种编程范式,满足面向对象编程的语言,一般会提供类、封装、继承等语法和概念来辅助我们来进行面向对象编程。类型被设计为将数...
  • qq_38308277
  • qq_38308277
  • 2018-03-13 16:26:59
  • 245

【bzoj3653】【谈笑风生】【dfs序+主席树】

Description 设T 为一棵有根树,我们做如下的定义: • 设a和b为T 中的两个不同节点。如果a是b的祖先,那么称“a比b不知道 高明到哪里去了”。 • 设a 和 b 为 T 中...
  • sunshinezff
  • sunshinezff
  • 2016-06-02 15:07:38
  • 329

bzoj 3653: 谈笑风生 (主席树+dfs序)

3653: 谈笑风生 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 720  Solved: 277 [Submit][Status][Dis...
  • clover_hxy
  • clover_hxy
  • 2016-12-25 19:23:46
  • 185

python中的访问控制

1. __xxx__ 类的一些特殊方法和属性,public 2. __xx 私有属性,代码预处理过程会将其转化为_className__xx,可以用预处理后的名字访问,用预处理前的名字访问会报错; ...
  • linshengchao123
  • linshengchao123
  • 2015-07-04 17:59:12
  • 445

Python的访问控制

《Dive Into Python》中说,如果一个Python function,class method或attribute以两个下划线开头,但是不以两个下划线结束,它就是private的,其他的一...
  • hansoft
  • hansoft
  • 2006-03-04 21:24:00
  • 3603
收藏助手
不良信息举报
您举报文章:与面试官谈笑风生 | Python面向对象之访问控制
举报原因:
原因补充:

(最多只允许输入30个字)