Python是面向对象的语言,在Python里一切皆对象,所以大部分情况下,我们都是通过类的方式来编程。
但是Python中的属性和方法在类的外部默认是可以访问的,而有些属性和方法我们只允许在类的内部使用,不允许在类的外部使用。这种情况下,可以使用类的私有属性和私有方法。
一、私有属性
Python中通过一对前缀下划线“__”的属性名来定义私有属性。
class Custom(object):
def __init__(self, name, money):
self.name = name
self.__money = money
c = Custom('tom', 100)
print(c.name)
print(c.__money)
运行结果:
Traceback (most recent call last):
tom
File "C:/Users/binn.wong/Desktop/python_demo/class_one_demo.py", line 13, in <module>
print(c.__money)
AttributeError: 'Custom' object has no attribute '__money'
在Custom类中,实现了两个属性,其中name是普通属性,__money属性是私有属性。在通过类对象访问私有属性__money时,代码报错了,说明我们不可以在类的外部访问类的私有属性。
但是,如果这个私有属性已经定义好了,我们又需要在外部知道私有属性的值,怎么办呢?
有些属性我们不希望在创建对象时直接传值,因为可能会出现脏数据(比如存款不能是负数),怎么避免呢?
这时,我们可以设置一对包含get和set的方法来给外部调用。
class Custom(object):
def __init__(self, name):
self.name = name
def get_money(self):
return self.__money
def set_money(self, money):
if money > 0:
self.__money = money
else:
self.__money = 0
print('参数值错误!')
c = Custom('tom')
print(c.name)
c.name = 'TOM'
print(c.name)
c.set_money(-100)
c.set_money(100)
print(c.get_money())
运行结果:
tom
TOM
参数值错误!
100
非私有属性可以在类的外部访问和修改,而私有属性只能通过包含set的方法来修改。我们在方法里加了数据判断的逻辑代码,先判断数据的有效性,再将数据赋值给属性,避免脏数据出现,此时,要在外面查看私有属性的值,可以通过包含get的方法来获取。
二、私有方法
私有方法和私有属性类似,方法名有两个前缀下划线'__',则表明该方法是私有方法。
class Interviewer(object):
def __init__(self):
self.wage = 0
def ask_question(self):
print('ask some question!')
def __talk_wage(self):
print('Calculate wage !')
def talk_wage(self):
if self.wage > 20000:
print('too high !')
else:
self.__talk_wage()
print('welcome to join us!')
me = Interviewer()
me.ask_question()
# me.__talk_wage()
me.wage = 30000
me.talk_wage()
print('-' * 20)
me.wage = 15000
me.talk_wage()
运行结果:
ask some question!
too high !
--------------------
Calculate wage !
welcome to join us!
在上面的类中,ask_question()方法是普通的方法,在类的外部可以直接调用,__talk_wage()方法是私有方法,只能在类的内部使用,如果在外部写调用的代码则报错。
要在外部调用__talk_wage(),只能间接的通过普通方法talk_wage()来调用。
三、私有方法的作用和说明
1.私有属性和私有方法只能在类内部使用。
2.定义私有方法和私有属性的目的主要有两个:保护数据或操作的安全性、向使用者隐藏核心开发细节。
3.可以间接的访问私有方法、属性。
虽然私有属性和私有方法不能直接从外部访问和修改,但是通过间接的方法,我们还是获取到了,也修改了。
这说明,在Python类中,没有真正的私有属性和私有方法。
不过,这并不是说私有属性和私有方法没有用,首先,外部不能直接使用了,其次,我们可以在访问私有属性和私有方法的间接方法中做一些必要的验证或干扰,保证数据的安全性,隐藏私有方法的实现细节。
四、私有方法、私有属性不能被子类继承
class Father(object):
def __init__(self):
self.home = 'China'
self.__house = 'house'
def make_money(self):
print('make money')
def __project(self):
print('project work')
class Son(Father):
def work(self):
print('work like a dog!')
s = Son()
print(s.home)
# print(s.__house)
s.work()
s.make_money()
# s.__project()
运行结果:
China
work like a dog!
make money
在父类中定义的普通属性和普通方法,子类都继承了,子类可以直接使用,但是父类中的私有属性和私有方法子类无法直接使用,因为子类不会继承父类的私有属性和私有方法。如果想访问,可以通过间接的方式访问。
五、Python中的下划线说明
1.不带下划线的变量和方法,是普通的变量和方法,在作用域内都可以正常使用,如果是类中定义的属性,则类对象可以在任何地方使用。
2.单前缀下划线“_”的变量和方法,这种变量可以在作用域内正常使用,如果定义在类中,外部可以使用,子类也可以继承。但是,在另一个py文件中通过from aaa import * 导入时,无法导入单下划线“_”开头的变量和方法。
3.双前缀下划线“__”的变量和方法,在作用域内也可以正常使用,如果定义在类中,则是私有属性和私有方法,在外部不能直接访问,子类也不会继承,要访问只能通过间接的方法。在另一个py文件中通过from aaa import * 导入时,也无法导入双下划线“__”开头的变量和方法。
4.单后缀下划线“_”的变量和方法,这种命名方法主要是为了避免与Python关键字冲突而采用的命名方法。
5.双前缀下划线加双后缀下划线“__init__”,这是Python中的魔法属性和魔法方法,都是有特殊含义的和特殊功能的,自己不要轻易定义这样的变量和方法。