组团学

面向对象-访问限制

阅读 (190233)

一、限制访问

  • 属性类型

    • 公有

      在内部和外部均可访问

      目前为止,正常定义在构造函数中

    • 私有

      • 如果要让内部属性不被外部访问,可以把属性名称前加上两个下滑线
      • python中实例的变量以__开头,就变成了一个私有属性(private),只能在类的内部访问,无法在类的外部直接访问
      • 属性前加一个下划线,这样的属性约定俗成的表示请把我看成私有的属性来用(虽然可以在类的外部直接访问),不要在外部直接访问
    • 特殊

      在python中,变量名类似__xxx__的属于特殊变量,特殊变量是可以直接在外部访问的,不是私有属性

  • 定义

    class Person(object): def __init__(self, name, age, sex, money, faceValue, word): self.name = name self.age = age self.sex = sex # 不能再外部直接访问__money的原因是python解释器对外把__money属性变为_Person__money。所以任然可以使用_Person__money来直接访问,但是强烈建议不要这么来用,因为不同版本的python解释器可能会把__money改成不同的名字 self.__money = money self._faceValue = faceValue self.__word__ = word
  • 使用

    class Person(object): def __init__(self, name, age, sex, money, faceValue, word): self.name = name self.age = age self.sex = sex self.__money = money self._faceValue = faceValue self.__word__ = word #定义公有方法间接访问私有属性 def getMoney(self): return self.__money def setMoney(self, value): self.__money = value def getFaceValue(self): return self._faceValue def setFaceValue(self, value): self._faceValue = value def play(self): print("---------play") self.__run() #私有方法,只能在类的内部调用 def __run(self): print("----------run")
    per = Person("liudh", 55, "男", 100, 99, "good") # 在类的外部访问对象属性 print(per.name) # 无法在类的外部直接访问私有属性 # print(per.__money) # 通过调用公有方法间接访问私有属性 print(per.getMoney()) per.setMoney(10) print(per.getMoney()) # print(per._Person__money) #以后不要这么使用 # 无法在类的外部直接调用私有方法 # per.__run() per.play() # print(per._faceValue) # 不要这么用 print(per.getFaceValue()) print(per.__word__)

二、@property

  • 目的

    让访问私有属性像访问公有属性那样方便,让私有属性可以使用点语法

  • 访问私有属性的原始方式:使用公有方法访问私有属性

    class Person(object): def __init__(self, name, age, sex, money): self.name = name self.age = age self.sex = sex self.__money = money def getMoney(self): return self.__money def setMoney(self, value): self.__money = value 通过访问公有方法间接访问私有属性 print(per.getMoney()) per.setMoney(1000) print(per.getMoney())
  • 想让访问私有属性的方式类似访问普通属性

    使用@property让私有属性可以使用点语法。但本质上还是调用公有方法访问的私有属性,只不过看起来比较美丽

    class Person(object): def __init__(self, name, age, sex, money): self.name = name self.age = age self.sex = sex self.__money = money # 取值,当 对象.money 时相当于访问了该方法 # 函数名为私有属性去掉下划线的部分 @property def money(self): return self.__money # 赋值,当 对象.money = 值 时相当于调用该方法,“值”当做参数传递进来(value = "值") @money.setter def money(self, value): self.__money = value per = Person("liudh", 55, "男", 100) # 访问私有属性的方式类似访问普通属性 print(per.money) per.money = 200 print(per.money)

三、动态给实例对象添加属性与方法

  • 准备代码

    class Person(object): def __init__(self, name): self.name = name def say(self): print("%s is a good man"%(self.name)) per1 = Person("liudh") per2 = Person("daolang") per1.say() per2.say()
  • 增加对象属性

    # 增加对象属性(实例化一个对象后,可以给对象绑定任意的属性和方法) per1.age = 55 #如果属性不存在则变为增加属性 print(per1.age) #给对象增加对象属性,只会给当前对象增加 # print(per2.age) #per2没有age属性
  • 增加类属性

    # 每个对象同时增加 Person.city = "北京" print(per1.city) print(per2.city)
  • 增加对象方法

    • 增加的既不是对象方法也不是类方法,有点类似静态方法

      # def run(): # print("--------run") # per1.run = run # per1.run()
    • 增加的确实是对象方法,但是需要手动给形参self传递参数

      # def run(self): # print("------------run") # self.say() # per1.run = run # per1.run(per1)
    • 合适的方式

      def run(self): print("------------run") self.say() from types import MethodType per1.run = MethodType(run, per1) per1.run()
  • 添加类方法

    def play(cls): print("-----play") from types import MethodType Person.play = MethodType(play, Person) Person.play()

四、使用__slots__属性限制增加

  • 思考

    想要限制实例的属性,不让对象随意添加属性,只能添加一些我们规定

  • 解决

    在定义类时,定义一个__slots__特殊属性,限制该类实例能添加的属性

    class Person(object): __slots__ = ("name", "age", "sex", "money") def __init__(self, name): self.name = name def say(self): print("%s is a good man"%(self.name))
  • 使用

    per = Person("liudh") per.age = 55 per.sex = "男" # per.faceValue = 100 # Person.city = "北京"
需要 登录 才可以提问哦