最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • Python3的构造函数和访问控制

    在面向对象编程中,构造函数和访问控制是我们经常用到的,并且是面向对象很重要的特性。

    构造函数

    虽然我们需要类的所有实例拥有共同的属性,
    但是我们不想让他们拥有共同的属性值,在对象创建后,我们可以调用一个函数来修改这些属性值。

    class Human():
        def initdata(self, myname, myage):
            self.name = myname
            self.age = myage
    
        def speak(self):
            print("大家好,我是%s;我的年龄是%s" % (self.name, self.age))
    
    luren_a = Human()
    luren_a.initdata("ruhua", 18)
    luren_a.speak()
    
    luren_b = Human()
    luren_b.initdata("zhaoritian", 17)
    luren_b.speak()

    我们发现上面那种方法重复繁琐,Python 语言可以通过定义一个名称为 __init__
    的函数,该函数叫做构造函数,在我们创建对象的时候,Python
    解释器会自动调用构造函数。构造函数也是类的成员函数,至少也要拥有一个参数,我们知道第一个参数是用来接收调用对象本身的,在构造函数内部,我们可以把各种属性绑定到该参数上。

    class Human():
        def __init__(self, myname, myage):
            self.name = myname
            self.age = myage
    
        def speak(self):
            print("大家好,我是%s;我的年龄是%s" % (self.name, self.age))
    
    luren_a = Human("ruhua", 18)     # Python 解释器会自动调用构造函数,并把 luren_a 作为第一个实参传给构造函数
    luren_a.speak()
    
    luren_b = Human("xingxing", 17)  # Python 解释器会自动调用构造函数,并把 luren_b 作为第一个实参传给构造函数
    luren_b.speak()

    由于在构造函数中我们把调用构造函数的对象本身传过去,然后通过这个对象初始化属性,这样一来,可以实现每个对象拥有不同的属性值。

    class Human():
        def __init__(self, myname):
            self.name = myname
    
    luren_a = Human("ruhua")
    luren_b = Human("xingxing")
    
    print(luren_a.name)  # luren_a 对象的 name
    print(luren_b.name)  # luren_b 对象的 name

    假如我们定义一个圆类,对于所有的圆类产生的对象都有 π 这个属性,并且该属性对所有圆对象的值都是一样的,
    我们没必要把 π 这个属性在每个对象创建的时候在构造函数内重新赋值,因为他们是一样的,我们可以把该属性定义在构造函数外面,我们称为该属性是属于类的(也就是所有对象共有一个)。

    class Circle():
        PI = 3.1415926
        def __init__(self, radius):
            self.radius = radius
    
        def showarea(self):
            print(self.radius * self.PI)
    
    redcircle = Circle(3)
    redcircle.showarea()    # 用的是类的属性 PI
    
    bluecircle = Circle(5)  # 用的是类的属性 PI
    bluecircle.showarea()
    
    Circle.PI = 1           # 可以通过类改变属性 PI
    print(redcircle.PI)     # 用的是类的属性 PI
    print(bluecircle.PI)    # 用的是类的属性 PI

    Python 如何实现让所有对象共享一个属性的呢?很简单,当 Python 发现类内存在属于类的属性时,只需要在每个对象初始化时,让对象中同名属性指向类属性即可。
    因此,我们试图通过某个对象修改属于类的属性,则对其它对象不起作用,因为修改的只是这个对象属性本身的指向,所有的其它对象属性还在指向这个属于类的属性。

    class Circle():
        PI = 3.1415926
        def __init__(self, radius):
            self.radius = radius
    
    redcircle = Circle(3)
    bluecircle = Circle(5)
    redcircle.PI = 1      # 只是改变了 redcircle 对象的属性 PI 指向
    
    print(redcircle.PI)   # 1
    print(bluecircle.PI)  # bluecircle 对象的属性 PI 还在指向 Cirle 类的属性 PI
    print(Circle.PI)      # Circle 类的属性 PI 只能通过 Cirle 类来改变

    访问控制

    我们在进行面向对象编程时,最好不要直接通过对象来访问(读或写)属性,而是通过类提供的函数进行读写属性操作,要养成良好的编程习惯。

    class Human():
        def __init__(self, myname):
            self.name = myname
    
        def getname(self):
            return self.name
    
        def setname(self, newname):
            self.name = newname
    
    luren_a = Human("ruhua")
    print(luren_a.getname())        # 访问属性
    luren_a.setname("wanghuahua")   # 修改属性
    print(luren_a.getname())

    人的天性都是非自觉的,程序员也是人,所以需要约束,我们刚刚讲过最好不要通过实例直接访问类的属性,
    那只是要求程序员自觉遵守,所以我们可以强制性约束,为了让内部属性不被外部访问,
    我们可以在属性的名称前加上两个下划线 __,在 Python 中,实例的变量名如果以 __
    开头,就变成了一个私有变量(private),私有变量只有在类的内部可以访问(读写),在类的外部不能访问(读写)。

    class Human():
        def __init__(self, myname):
            self.__name = myname
    
        def getname(self):
            return self.__name      # 类的内部可以访问
    
        def setname(self, newname):
            self.__name = newname   # 类的内部可以访问
    
    luren_a = Human("ruhua")
    print(luren_a.getname())
    luren_a.setname("wanghuahua")
    print(luren_a.getname())
    
    print(luren_a.__name)          # 报异常,因为类的外部无法访问
    luren_a.__name = "wanghuahua"  # 报异常,因为类的外部无法访问

    有时候,我们会遇到以单下划线开头的变量,这样的实例变量在外部是可以访问的,我们最好不要去访问,这是一个不成文的约定。

    class Human():
        def __init__(self, myname):
            self._name = myname
    
    luren_a = Human("ruhua")
    print(luren_a._name)  # 类的外部可以访问 _name,但最好不要访问,要遵守约定

    Python 本身不进行访问控制的语法检查,以双下划线开头的变量不能访问的原因,
    仅仅是因为 Python 在类内部把所有以 __ 开头的变量进行了更名,我们如果知道更改后的属性名,就可以在外部进行访问该属性,注意不同版本的
    Python 解释器可能会把该变量改成不同的变量名。

    class Human():
        def __init__(self, myname):
            self.__name = myname
    
    luren_a = Human("ruhua")
    print(luren_a._Human__name)    # Python 3.7 版本把名字改成了 _Human__name
    Human.__name = "wanghuahua"
    print(luren_a.__name)          # Python 只对类内部 __开头的变量做改名,所以可以访问
    
    # 我们可以通过 id 函数知道它们并不是一个变量
    print(id(luren_a.__name))
    print(id(luren_a._Human__name))
    

    本节重要知识点

    构造函数如何定义

    Python 实现访问控制的方法

    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » Python3的构造函数和访问控制
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情