zoukankan      html  css  js  c++  java
  • Python3中_和__的用途和区别

     

    访问可见性问题

    对于上面的代码,有C++、Java、C#等编程经验的程序员可能会问,我们给Student对象绑定的nameage属性到底具有怎样的访问权限(也称为可见性)。因为在很多面向对象编程语言中,我们通常会将对象的属性设置为私有的(private)或受保护的(protected),简单的说就是不允许外界访问,而对象的方法通常都是公开的(public),因为公开的方法就是对象能够接受的消息。在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头,下面的代码可以验证这一点。

    class Test:
    
        def __init__(self, foo):
            self.__foo = foo
    
        def __bar(self):
            print(self.__foo)
            print('__bar')
    
    
    def main():
        test = Test('hello')
        # AttributeError: 'Test' object has no attribute '__bar'
        test.__bar()
        # AttributeError: 'Test' object has no attribute '__foo'
        print(test.__foo)
    
    
    if __name__ == "__main__":
        main()

    但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来“妨碍”对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是“We are all consenting adults here”。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。

    class Test:
    
        def __init__(self, foo):
            self.__foo = foo
    
        def __bar(self):
            print(self.__foo)
            print('__bar')
    
    
    def main():
        test = Test('hello')
        test._Test__bar()
        print(test._Test__foo)
    
    
    if __name__ == "__main__":
        main()

    在实际开发中,我们并不建议将属性设置为私有的,因为这会导致子类无法访问(后面会讲到)。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重。这种做法并不是语法上的规则,单下划线开头的属性和方法外界仍然是可以访问的,所以更多的时候它是一种暗示或隐喻,关于这一点可以看看我的《Python - 那些年我们踩过的那些坑》文章中的讲解。

    面向对象的支柱

    面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里我们先说一下什么是封装。我自己对封装的理解是“隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口”。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。

    练习

    练习1:定义一个类描述数字时钟

    class Clock(object):
        """数字时钟"""
    
        def __init__(self, hour=0, minute=0, second=0):
            """初始化方法
    
            :param hour: 时
            :param minute: 分
            :param second: 秒
            """
            self._hour = hour
            self._minute = minute
            self._second = second
    
        def run(self):
            """走字"""
            self._second += 1
            if self._second == 60:
                self._second = 0
                self._minute += 1
                if self._minute == 60:
                    self._minute = 0
                    self._hour += 1
                    if self._hour == 24:
                        self._hour = 0
    
        def __str__(self):
            """显示时间"""
            return '%02d:%02d:%02d' % 
                   (self._hour, self._minute, self._second)
    
    
    def main():
        clock = Clock(23, 59, 58)
        while True:
            print(clock)
            sleep(1)
            clock.run()
    
    
    if __name__ == '__main__':
        main()

    练习2:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法。

    from math import sqrt
    
    
    class Point(object):
    
        def __init__(self, x=0, y=0):
            """初始化方法
            
            :param x: 横坐标
            :param y: 纵坐标
            """
            self.x = x
            self.y = y
    
        def move_to(self, x, y):
            """移动到指定位置
            
            :param x: 新的横坐标
            "param y: 新的纵坐标
            """
            self.x = x
            self.y = y
    
        def move_by(self, dx, dy):
            """移动指定的增量
            
            :param dx: 横坐标的增量
            "param dy: 纵坐标的增量
            """
            self.x += dx
            self.y += dy
    
        def distance_to(self, other):
            """计算与另一个点的距离
            
            :param other: 另一个点
            """
            dx = self.x - other.x
            dy = self.y - other.y
            return sqrt(dx ** 2 + dy ** 2)
    
        def __str__(self):
            return '(%s, %s)' % (str(self.x), str(self.y))
    
    
    def main():
        p1 = Point(3, 5)
        p2 = Point()
        print(p1)
        print(p2)
        p2.move_by(-1, 2)
        print(p2)
        print(p1.distance_to(p2))
    
    
    if __name__ == '__main__':
        main()

    说明:本章中的插图来自于Grady Booch等著作的《面向对象分析与设计》一书,该书是讲解面向对象编程的经典著作,有兴趣的读者可以购买和阅读这本书来了解更多的面向对象的相关知识。

  • 相关阅读:
    文件操作
    MFC
    MFC
    MFC
    MFC
    大陆居民身份证验证方法(java)
    java validator的原理与使用
    解析搜狗词库(python)
    ICTCLAS改进的java版分词软件
    mvn打包
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/10811623.html
Copyright © 2011-2022 走看看