私有化&property

xx: 公有变量

_x: 单前置下划线,私有化属性或⽅法, from somemodule import *禁⽌导
⼊,类对象和⼦类可以访问

__xx: 双前置下划线,避免与⼦类中的属性命名冲突, ⽆法在外部直接访
问(名字重整所以访问不到)

__xx__:双前后下划线,⽤户名字空间的魔法对象或属性。 例
如: __init__ , __ 不要⾃⼰发明这样的名字

xx_:单后置下划线,⽤于避免与Python关键词的冲突

通过name mangling(名字重整(⽬的就是以防⼦类意外重写基类的⽅法或者
属性)如: _Class__object) 机制就可以访问private了。

“_”:以单下划线开头的表示的是protected类型的变量,即只能允许其本身与子类进行访问;同时表示弱内部变量标示,如,当使用"from moduleName import *"时,不会将以一个下划线开头的对象引入。

“__”:双下划线的表示的是private类型的变量。只能是允许这个类本身进行访问了连子类也不可以,这类属性在运行时属性名会加上单下划线和类名。

注意:1.单下划线开头,外部仍能访问; 双下划线开头,解释器会将变量改名字,作用是避免名字冲突;不具有权限控制,外部仍能访问

2. 变量命名要有明确含义

私有化产生的背景:

在开发过程中,如果不希望外界随便动我的属性,往往就会把属性对外隐藏起来

什么叫对外隐藏?

就是,你能够看到对象的属性,但是你修改不了,或者单独取一个属性看,都看不了,比如p = Person('Jack','18'),我要单独看这个对象的名字,这样是看不了的

class Student:
    def __init__(self, name, age, score):
        self.__name = name
        self.__age = age
        self.__score = 59

    def __str__(self):
        return '姓名:{},年龄:{},考试分数:{}'.format(self.__name, self.__age, self.__score)


s = Student('Jack', 20, 59)
print(s)
print(s.__name)

 

 因此,我们需要定义公有的get方法和set方法,暴露给外面,便于赋值和取值

 封装:1.私有化属性,2.定义公有的set和get方法

 

__属性:就是将属性私有化,访问范围就仅仅限于类中了,只能在类中进行修改,因此在类里面定义set方法,进行修改  

class Student:
    def __init__(self, name, age, score):
        self.__name = name
        self.__age = age
        self.__score = 59

    # 定义公有的set和get方法
    # set是为了赋值
    def setAge(self, age):
        self.__age = age

    def __str__(self):
        return '姓名:{},年龄:{},考试分数:{}'.format(self.__name, self.__age, self.__score)


s = Student('Jack', 20, 59)
print(s)
# 对私有化属性age的值进行修改
s.setAge(30)
print(s)

 

 私有化的好处:

1.隐藏属性不被外界随意修改

2.也可以修改:

  通过一个函数完成:def setXXX(self, xxx):

   可以对传过来的值(赋值),进行筛选校验,

    if xxx是否符合条件

      赋值

    else:

      不赋值

 3.如果想获取具体的某个属性

  使用get函数

    def getXXX(self):

      return self.__xxx

class Student:
    def __init__(self, name, age, score):
        self.__name = name
        self.__age = age
        self.__score = 59

    # 定义公有的set和get方法
    # set是为了赋值
    def setAge(self, age):
        if age < 60:
            self.__age = age
        else:
            print('年龄超过60岁')

    def __str__(self):
        return '姓名:{},年龄:{},考试分数:{}'.format(self.__name, self.__age, self.__score)


s = Student('Jack', 20, 59)
print(s)
# 对私有化属性age的值进行修改
s.setAge(30)
print(s)

s.setAge(65)

 使用get函数

class Student:
    def __init__(self, name, age, score):
        self.__name = name
        self.__age = age
        self.__score = 59

    # 定义公有的set和get方法
    # set是为了赋值
    def setAge(self, age):
        if age < 60:
            self.__age = age
        else:
            print('年龄超过60岁')

    def getAge(self):
        return self.__age

    def __str__(self):
        return '姓名:{},年龄:{},考试分数:{}'.format(self.__name, self.__age, self.__score)


s = Student('Jack', 20, 59)
print(s)
# 对私有化属性age的值进行修改
s.setAge(30)
print(s)

s.setAge(65)
print(s.getAge())

 

 其实,通过__age这样的操作,系统给这样的属性自动改名字了,改成_Student__age,这样通过s._Student__age还是可以访问到的

因此私有化,就是底层做了这样的包装,封装,

我们可以通过dir(s)这样的方法查看对象有哪些属性

 

 我们在开发中看到另外一种处理私有化的方法,装饰器

(1)使用@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。

# 在开发中看到一些私有化处理:装饰器
class Student:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    @property
    def age(self):
        return self.__age


s = Student('Jack', 19)
s.name = 'Rose'
print(s.name)
print(s.age)  # 默认就是找类里面的age方法,因为加了装饰器,因此可以不用s.age()这样,就当成属性一样
print(s.__dir__())

# 在开发中看到一些私有化处理:装饰器
class Student:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    # 一定先有getxxx
    @property
    def age(self):
        return self.__age

    # 再有set,因为set依赖get
    @age.setter
    def age(self, age):
        if age > 0 and age < 100:
            self.__age = age
        else:
            print('不在规定范围内')


s = Student('Jack', 19)
s.name = 'Rose'   # 没有私有化的属性
print(s.name)
print(s.age)  # 默认就是找类里面的age方法,因为加了装饰器,因此可以不用s.age()这样,就当成属性一样
s.age = 30   # 可以将私有化的属性,像没有私有的属性那样修改
print("修改后:", s.age)
s.age = 120
print('修改后1:', s.age)

 

讲私有化方法和from module import * 导入私有化属性和方法会报undefined的错误的

class DataSet(object):
  @property
  def method_with_property(self): ##含有@property
      return 15
  def method_without_property(self): ##不含@property
      return 15

l = DataSet()
print(l.method_with_property) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
print(l.method_without_property())  #没有加@property , 必须使用正常的调用方法的形式,即在后面加()

(2)与所定义的属性配合使用,这样可以防止属性被修改。

由于python进行属性的定义时,没办法设置私有属性,因此要通过@property的方法来进行设置。这样可以隐藏属性名,让用户进行使用的时候无法随意修改。

class DataSet(object):
    def __init__(self):
        self._images = 1
        self._labels = 2 #定义属性的名称
    @property
    def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户没办法随意修改。
        return self._images 
    @property
    def labels(self):
        return self._labels
l = DataSet()
#用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。

  

https://blog.csdn.net/qq_34765552/article/details/75670274

 

posted @ 2020-02-29 10:20  GumpYan  阅读(274)  评论(0编辑  收藏  举报