Python_私有属性和私有方法

1. 应用场景和定义方式

要定义对象的属性, 就在初始化方法内部,使用self.属性,然后使用赋值语句可以定义一个属性, 要定义方法我们就使用def 关键字, 跟上方法名,方法的第一个参数应该是self。在我们的开发中, 有的时候可能会碰到一种情况, 对象的属性或者方法, 我们只希望在对象的内部进行访问, 而不希望在外界访问到这些属性和方法, 这种属性和方法我们就把它叫做私有属性和私有方法, 用大白话来讲, 私有属性和私有方法就是对象的隐私, 既然是隐私, 那么私有属性就是不希望对外界公开的属性, 那么私有方法就是不希望对外界公开的方法。

如果在定义属性和方法的时候, 在属性名前,或者在方法名前,增加两个下划线, 增加了两个下划线之后, 这个属性或者方法,就变成了私有属性或者私有方法。

我们定义一个woman 类,女人有一个属性叫name, 还有一个叫年龄, 女人还有很多小秘密,所以我们在给女人定义一个secret 方法, 两个属性和一个方法明确之后。

使用class关键字定义一个Woman 类, 然后使用def 关键字找到初始化方法,在初始化方法中先来增加一个name 的形参, 然后再来在初始化方法中使用使用self. 来定义一个name 的属性 self.name = name 和一个age 的属性 self.age = 18, 以上就是定义常规的属性和方法, 还没有增加下划线使其成为私有的。这样一个初始化方法就准备完成了。

再定义一个secret 的方法, def secret (self), 使用self 把name的属性跟上,self.name,再使用self把age 的属性跟上, self.age, 这样secret 就准备完成了。

接下来我们就可以使用Woman 类来创建一个对象, 给变量起个名字, 叫xiaofang, 使用Woman 类来指定一下xiaofang 的名字, xiaofang = Woman("小芳"), 对象创建完成, 我们就可以使用print 函数先把xiaofang 的年龄做一个输出, print(xiaofang.age), 然后再让xiaofang 来调用一下小秘密的方法, xiaofang.secret(), 总结:一个简单的类Woman 就定义完成后, 我们创建一个对象xiaofang,输出了对象的属性, print(xiaofang.age), 并且让对象调用方法, xiaofang.secret().

要定义私有属性, 比如可以在属性age 前面增加两条下划线, self.__age = 18, 属性名修改完成之后, 在secret 方法中和类的外部, 同样要做一个修改, 按道理都要修改为 self.__age = 18, 但只有在Woman类中secret方法中会有智能提示, 类的外部不会有智能提示, 且将类外的self.age 修改为 self.__age 时会报错。这个是私有属性的特点, 一句话讲, 私有属性在类的外部是不能够被直接访问的。

在对象的方法内部,是可以访问到对象自己的私有属性, 私有属性只是禁止在外部访问, 当一个类的方法中使用到私有属性, 而这个方法又被外部调用时, 是不会报错的, 只要不要直接在类的外部直接输出对象的私有属性就可以了, 否则会报错。

class Women:
    def __init__(self, name):
        self.name = name
        self.__age = 18
    
    def secret(self):
        # 在对象的方法内部是可以访问到对象的私有属性的
        # 
        print("%s 的年龄是 %d" % (self.name, self.__age))

# 创建对象 xiaofang
xiaofang = Women("小芳")

# 先把 xiaofang 的年龄做一个输出
# 私有属性__age 再外界不能直接被直接访问
# 私有属性禁止在外界访问, 但在对象的方法内部仍然可以正常访问
print(xiaofang.__age)  #会报错,会被告知 Women 这个类没有__age这个属性

# 再让xiaofang 来调用一下 secret 的方法
# 通过调用secret() 方法可以访问到私有属性__age
xiaofang.secret()

如果某些方法也不希望被类的外界调用, 我们同样可以在方法名前增加两条下划线, 如 def __secret(self), 增加完成之后, 这时在外部尝试调用这个方法时是没有智能提示的, 运行还会报错, 说明了私有方法同样不允许在外界直接访问。

从外界访问私有方法会报错:

2.伪私有属性和伪私有方法

在python这门语言中, 是没有真正意义上的私有的。

注意: 在日常开发中, 不要使用这种方式, 访问对象的私有属性或私有方法,因为私有属性和私有方法是属于对象的隐私, 既然是隐私, 就不要再外界轻易的访问。

可以使用这种方式访问私有方法,在类的外部将 xiaofang.__age,改为 xiaofang._Women__age, 就不会报错了, 就能从类的外部访问到对象的私有属性。

也可以使用下面的方式在类的外部访问到私有方法, 将xiaofang.__secret, 改为xiaofang._Women__secret, 就不会报错, 就能从类的外部访问到对象的私有属性 。

在python 中, 是没有真正意义上的私有私有属性和私有方法的,只有伪私有属性和伪私有方法。

class Women:
    def __init__(self, name):
        self.name = name
        self.__age = 18
    
    def __secret(self):
        # 在对象的方法内部是可以访问到对象的私有属性的
        # 
        print("%s 的年龄是 %d" % (self.name, self.__age))

# 创建对象 xiaofang
xiaofang = Women("小芳")

# 先把 xiaofang 的年龄做一个输出
# 私有属性__age 再外界不能直接被直接访问
# 私有属性禁止在外界访问, 但在对象的方法内部仍然可以正常访问
print(xiaofang._Women__age)  #会报错,会被告知 Women 这个类没有__age这个属性

# 再让xiaofang 来调用一下 secret 的方法
# 通过调用secret() 方法可以访问到私有属性__age
xiaofang._Women__secret()

运行结果:

扩展1:子类对象不能直接访问

父类中定义了一个私有属性和私有方法, 意味着这个私有属性和私有方法是父类的隐私, 既然是父类的隐私, 我们就不能在子类的方法外部访问到父类的隐私。

下面就使用代码的方式来验证一下,看看子类对象能不能在自己的方法的内部访问到父类中定义的私有属性或者调用父类中定义的私有方法。首先把两个类准备一下, 先使用class 关键字定义一个A类, 然后使用pass 关键字做一个占位, 一个空的A类创建完成, 然后在使用一个class 关键字定义一个B 类, 让 B类来继承一下A类, class B(A), 然后在使用一个pass 关键字来做一个占位。两个类准备完成, 就可以在主程序中使用B 类创建一个子类对象, b = B(), 把子类对象做一个输出,print(b), 运行一下程序, 控制台输出了子类对象在内存中的地址。

class A:
    pass


class B(A):
    pass

# 创建一个子类对象
b = B()
print(b)

运行结果:

下面在父类中, 使用def 关键字找到 __init__(self) 这个初始化方法, 先定义一个公有属性, self.num1 = 100, 然后再定义私有属性, self.__num2 = 200, 使用一个def 关键字定义一个私有方法, def __test(self), 在私有方法内部, 我们就使用print函数做一个输出,在私有方法内部把私有变量的两个属性num1 和num2 做一个输出,  print(“私有方法 %d %d” % (self.num, self.__num2)), 现在两个属性准备完成, 一个私有方法准备完成,我们不能在主程序中直接访问到对象的私有属性或者调用对象的私有方法, 如果硬要访问, 程序会报错。

在B类这个子类中来定义一个demo方法, def demo(self), 然后在demo 方法中, 要验证两个点, 第一点,要验证访问父类的私有属性,print ("访问父类的私有属性 %d" % self.__num2), 写self.num2时, 没有智能提示, 说明在子类的方法中是不能直接访问父类的私有属性的, 因为这个属性是父类的隐私, 现在在主程序中让b 这个对象来调用demo 这个方法,b.demo(), 运行一下, 程序执行到第17行就报错了, 在第17行我们尝试访问在父类中定义的私有属性, self.__num2, 但是在执行时告诉我们 B 对象并没有__num2这个属性, 小结:在子类的对象方法中, 不能访问到父类的私有属性。 第二点,要验证一下,调用父类的私有方法, 和第一点同理。

class A:
    def __init__(self):

        # 定义公有属性 num1
        self.num1 = 100

        # 定义私有属性 __num2
        self.__num2 = 200

    # 定义一个私有方法
    # 在对象的方法内部, 是可以访问到对象的公有属性和私有属性的
    def __test(self):
        print("私有方法 %d %d" %(self.num1, self.__num2))

    

class B(A):
    
    def demo(self):

        # 1. 在子类的方法中,不能访问父类的私有属性
        #print("访问父类的私有属性 %d" % self.__num2)   #会报错

        # 2. 调用父类的私有方法
        # self.__test()  # 会报错
        pass

# 创建一个子类对象
b = B()
print(b)

b.demo()

# 在外界不能直接访问对象的私有属性或者调用私有方法
# print(b.__num2)   #会报错
# b.__test()   # 会报错

运行结果:

扩展2:通过父类方法间接访问私有属性和私有方法

在外界是可以访问到父类的公有属性以及调用公有方法。

在子类的方法内部,能访问到父类的公有属性和调用父类的公有方法。

 

class A:
    def __init__(self):

        # 定义公有属性 num1
        self.num1 = 100

        # 定义私有属性 __num2
        self.__num2 = 200

    # 定义一个私有方法
    # 在对象的方法内部, 是可以访问到对象的公有属性和私有属性的
    def __test(self):
        print("私有方法 %d %d" %(self.num1, self.__num2))
    
    # 在父类中定义一个公有方法
    def test(self):
        print("父类的公有方法")


    
    

class B(A):
    
    def demo(self):

        # 1. 在子类的方法中,不能访问父类的私有属性
        #print("访问父类的私有属性 %d" % self.__num2)   #会报错

        # 2. 调用父类的私有方法
        # self.__test()  # 会报错
        pass

# 创建一个子类对象
b = B()
print(b)

b.demo()

# 在外界可以访问父类的公有属性和调用公有方法
print(b.num1)
b.test()


# 在外界不能直接访问对象的私有属性或者调用私有方法
# print(b.__num2)   #会报错
# b.__test()   # 会报错

输出结果:

 

 

先在demo 代码内部使用print 函数做一个输出, print("子类方法 %d" % self.num1), 输入self.num1 的过程中,会有智能提示,  接下来再使用self. 来调用一下父类中定义的test() 方法,同样也有智能提示,self.test(), 执行一下,看看主程序中, 让子类对象调用demo方法的时候, 以上两句代码能不能正常执行, 输出“子类方法 100”和 “父类的公有方法”, 子类方法中把父类定义的公有属性做了一个输出, 输出100, 同时在子类方法中同样也可以调用到父类中定义的公有方法。

 

子类对象能够调用父类的公有方法, 如果我们在父类的公有方法中访问父类的私有属性或者调用父类的私有方法, 这样的代码能够正常执行, 

在父类自己的方法中,是可以访问到父类自己的私有属性的, 在父类自己的公有方法中, 是可以调用自己的私有方法的,把父类的公有方法做了一个调整,在父类的公有方法内部访问了父类的私有属性,print("父类的公有方法 %d " % self.num2), 在父类的公有方法内部调用父类的私有方法,self.__test(), 但没有改动子类的demo方法, 在子类demo中,仍然是单纯的调用父类的公有方法而已,self.test(), 现在改造完成, 再来运行一下程序, 看看在父类的公有方法中, 能不能把自己的私有属性输出在控制台, 以及能不能调用自己的私有方法, 运行后, 父类的私有属性 200 会输出在控制台,并且也调用了自己的私有方法,在私有方法内部, 把两个属性值同样也做了一个输出。

总结 :虽然子类对象不能在自己的方法内部, 直接访问到父类的私有属性或调用私有方法, 但子类对象可以通过父类的公有方法间接访问到私有属性或私有方法。

class A:
    def __init__(self):

        # 定义公有属性 num1
        self.num1 = 100

        # 定义私有属性 __num2
        self.__num2 = 200

    # 定义一个私有方法
    # 在对象的方法内部, 是可以访问到对象的公有属性和私有属性的
    def __test(self):
        print("私有方法 %d %d" %(self.num1, self.__num2))
    
    # 在父类中定义一个公有方法
    # 在父类自己定义的方法中, 是可以访问到自己的私有属性的
    def test(self):
        print("父类的公有方法 %d" % self.__num2)

        # 可以间接的通过父类的公有方法, 访问到父类中定义的私有属性和私有方法
        self.__test()


    
    

class B(A):
    
    def demo(self):

        # 1. 在子类的方法中,不能访问父类的私有属性
        #print("访问父类的私有属性 %d" % self.__num2)   #会报错

        # 2. 调用父类的私有方法
        # self.__test()  # 会报错
        

        # 3. 访问父类的公有属性   >子类方法中把父类定义的公有属性100 做了一个输出
        print("子类方法 %d" % self.num1)


        # 4. 调用父类的公有方法 >在子类方法中也可以定义到父类定义的公有方法
        self.test()
        pass

# 创建一个子类对象
b = B()
print(b)

b.demo()

# 在外界可以访问父类的公有属性和调用公有方法
print(b.num1)
b.test()


# 在外界不能直接访问对象的私有属性或者调用私有方法
# print(b.__num2)   #会报错
# b.__test()   # 会报错

运行结果:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值