zoukankan      html  css  js  c++  java
  • 我的Python学习笔记(三):私有变量

    一、私有变量的定义

    在Python中,有以下几种方式来定义变量:

    • xx:公有变量
    • _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入
    • __xx:双前置下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到)
    • __xx__:双前后下划线,系统定义名字(不要自己发明这样的名字)
    • xx_:单后置下划线,用于避免与Python关键词的冲突

    如以下例子所示,我在test类中定义了num,_num 和 __num三个属性,并创建了test的类对象t,对这三个属性进行访问,__num不能被访问到

    class test(object):
        def __init__(self):
            self.num = 10
            self._num = 20
            self.__num = 30
    
    t = test()
    print(t.num)    # 10
    print(t._num)   # 20
    # print(t.__num)  # AttributeError: 'test' object has no attribute '__num'

    可以使用命令dir查看t中的属性和方法,__num的名字已经被重整为“_test__num”了,可以使用t._test__num对__num进行访问

    注:虽然私有变量可以通过_类名__变量名来访问,但强烈建议不要这样做

    二、使用不同方法导入模块,模块中私有变量的使用区别

    在使用不同方法导入模块后,是否能使用模块中的私有属性和方法,有以下两种情况

    • 在使用 from somemodule import * 导入模块的情况下,不能导入或使用私有属性和方法
    • 在使用 import somemodule 导入模块的情况下,能导入并使用私有属性和方法

    首先我们先创建一个test.py文件,将下面代码复制进去:

    num = 10
    _num = 20
    __num = 30
    
    def test():
        print("--test--")
    
    def _test2():
        print("--test2--")
    
    def __test3():
        print("---test3--")
    • 使用 from somemodule import * 进行导入,不能导入私有变量,结果如下:
    In [1]: from test import *
    
    In [2]: num
    Out[2]: 10
    
    In [3]: _num
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-3-6dd7111d6a95> in <module>()
    ----> 1 _num
    
    NameError: name '_num' is not defined
    
    In [4]: __num
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-4-f0ba2c4a214a> in <module>()
    ----> 1 __num
    
    NameError: name '__num' is not defined
    
    In [5]: test()
    --test--
    
    In [6]: _test2()
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-6-d29889233d08> in <module>()
    ----> 1 _test2()
    
    NameError: name '_test2' is not defined
    
    In [7]: __test3()
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-7-17e592a156f3> in <module>()
    ----> 1 __test3()
    
    NameError: name '__test3' is not defined
    • 使用 import somemodule 进行导入,能导入私有变量,结果如下:
    In [8]: import test
    
    In [9]: test.num
    Out[9]: 10
    
    In [10]: test._num
    Out[10]: 20
    
    In [11]: test.__num
    Out[11]: 30
    
    In [12]: test.test()
    --test--
    
    In [13]: test._test2()
    --test2--
    
    In [14]: test.__test3()
    ---test3--

    三、对类中的私有属性进行操作的方法

    如果你想对类中的私有属性进行操作时,有以下三种方法:

    1、getter和setter:

    添加getter和setter方法,类对象通过调用这两种方法来对私有属性进行操作

    class test(object):
        def __init__(self):
            self.__num = 10
            
        def getNum(self):
            return self.__num
    
        def setNum(self, value):
            self.__num = value
    
    t = test()
    print(t.getNum())   # 10
    t.setNum(20)
    print(t.getNum())   # 20

      2、property方法

    class test(object):
        def __init__(self):
            self.__num = 10
    
        def getNum(self):
            return self.__num
        
        def setNum(self, value):
            self.__num = value
    
        num = property(getNum,setNum)
    
    t = test()
    print(t.num)   # 10
    t.num = 20
    print(t.num)   # 20

    关于property方法,我们来看下官方文档:

    由文档可得:

    • property方法包含四个参数,分别为fget,fset,fdel,doc,分别对应getter方法,setter方法,deleter方法和方法说明
    • property()方法返回一个property属性,如果c是C的实例,那么c.x会调用getter方法,c.x = value会调用setter方法,而del c.x会调用deleter方法

      

      3、@property

    class test(object):
        def __init__(self):
            self.__num = 10
    
        @property
        def num(self):
            return self.__num
    
        @num.setter
        def num(self, value):
            self.__num = value
    
    t = test()
    print(t.num)   # 10
    t.num = 20
    print(t.num)   # 20

    关于@property,官方文档如下:

    根据文档可得:

    • 我们可以把property()方法当成一个装饰器来使用,使用@property对方法进行装饰
    • 装饰器@property把方法x()转换成了与方法名同名的getter方法,"I'm the 'x' property."是property的doc参数
    • 调用方法和property()方法一样
  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/semon-code/p/8242062.html
Copyright © 2011-2022 走看看