下划线的几种表现形式
一、下划线的几种常见出现形式
python中变量属性方法得命名中经常会出现下划线,并且不同的下划线形式还有不同的含义,掌握其代表的不同含义,对于理解python代码来说也是很有帮助的。先来看一段代码:
class Member(object):
def __init__(self, card_id, name, birth ):
self.__card_id = card_id
self._name = name
self.birth = birth
def print_info(self):
print('%s(%s): %d' % (self.__card_id,self._name, self.birth))
s1=Member("1101","张三","0901")
print(s1._name) #张三
print(s1.birth) #0901
print(s1.__card_id)
#AttributeError: 'Student' object has no attribute 'name'
运行上述代码会发现,无法输出s1.__card_id这个属性了,而s1._name和s1.birth是可以输出的,这就涉及到下划线在python中的特殊作用了。
在Member内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据。
但是,有时候类的内部属性不想在外部被访问,比如Menber类中,其属性__card_id(此属性名中间的下划线是隔开单词的作用,是一种常见的python命名规则)以双下划线开头,在Python中,实例的变量名如果以__双下划线开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,就可以保护属性__card_id不被随意调用和更改,这样通过访问限制的保护,代码更加健壮。
归纳以下下划线的几种形式和作用:
- 以双下划线开头的变量属性和方法:受保护的对象,不能访问不能调用。
- 变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量。
- 以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
- 只要开头没有下划线,放在其他任何地方都没有任何特殊用法和含义,如:card_id , card__id , cardid_ , cardid__等,爱咋咋地,你喜欢就好。
然后呢,又来找事,就是偏要访问以双下划线开头的变量咋弄,可以啊,给你访问啊,但是你不要像上面那样直接啊,看这里:
print(s1._Member__card_id)
不能直接访问__card_id是因为Python解释器对外把__card_id变量改成了_Member__name,所以,仍然可以通过_Member__card_id来访问__card_id变量。
但是呢,这么干有风险,因为不同版本的Python解释器可能会把__card _id改成不同的变量名。
二、通过访问器方法访问私有变量
class Member(object):
def __init__(self, card_id, name, birth):
self.__card_id = card_id
self._name = name
self.birth = birth
def print_info(self):
print('%s(%s): %d' % (self.__card_id,self._name, self.birth))
def get_cardid(self):
return self.__card_id
def set_cardid(self,cardid):
if len(cardid) != len(self.__card_id):
raise ValueError('卡号长度不能变') #避免传入不合理的参数
self.__card_id = cardid
s1=Member("1101","张三","0901")
s1.get_cardid()
s1.set_cardid("1001") #重新设置卡号
s1.set_cardid("1000001") #会报错:卡号长度不能变
在Member类中定义了两个方法,get_cardid和set_cardid,通过这两个函数达到访问属性__card_id和重新设置__card_id的取值,在set_cardid函数中还加入了控制逻辑:卡号长度设置不合理时会报错,可以对参数做检查,避免传入不合理的参数。
将私有变量的访问和赋值通过构造方法来实现,看似是将简单的问题变复杂了,实际是保护对象内部的状态不被随意修改。