python 並沒有 private 這種東西,只能透過命名的方式希望不要讓別人存取.而命名方式就是在變數或方法前面加上_
.
>>> class Animal:
... age = 0
... def __init__(self,name):
... self.name = name
... def _count_age(self,age):
... return age * 10
... def add_age(self,new_age):
... Animal.age = self._count_age(new_age)
... def print_age(self):
... print(Animal.age)
...
>>> a1 = Animal('Cat')
>>> a1.add_age(5)
>>> a1.print_age()
50
還是可以呼叫得到.
>>> a1._count_age(3)
30
寫一隻 my_caculate.py
定義兩個 function :
def add(a,b):
return a + b
def _sum(a,b):
return a + b
把 my_caculate 模組 import 進來,python 會避開_
開頭的 function,所以_sum
不會被 import 進來.
>>> from my_caculate import *
>>> add(1,2)
3
>>> _sum(2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_sum' is not defined
但如果使用下面方式 import 就可以呼叫得到.
>>> from my_caculate import _sum
>>> _sum(2,3)
5
underscore 目前已經知道有__名稱__
和_名稱
,另外還有兩種是名稱_
和__名稱
共 4 種寫法.
名稱_
主要是用來避免與 built-in 名稱相同,比如說 puthon 已經有定義 list 這名稱,但如果還是很想用 list 這名稱當作自定義的變數時,就可以在 list 後面加上 underscore 變成 list_.
__名稱
在遇到 class 與 subclass 都使用到相同的變數名稱時,會發生命名碰撞的問題,如下當子類別使用父類別的方法時,由於 self 是子類別的 instance 所以 get_sum function 裡的 self.sum 是子類別 Calc2 的實體變數 sumn 所以 2 + 5 答案會是 7.
>>> class Calc1:
... sum = 10
... def get_sum(self):
... return self.sum
...
>>> class Calc2(Calc1):
... def add_sum(self,num):
... self.sum = 2
... return self.get_sum() + num
...
>>> c1 = Calc1()
>>> c1.sum
10
>>> c2 = Calc2()
>>> c2.add_sum(5)
7
>>> c2.sum
2
其實上面的案例用物件導向的方式思考感覺是蠻合理的,因為使用的是 Calc2 所以計算時當然是希望用的是 Calc2 的 sum.但如果改成使用__sum
這時候 Calc1 的__sum
跟 Calc2 的__sum
就不會發生命名碰撞了.既然不會發生碰撞所以當你呼叫 Calc1 的 get_sum 其實 Calc1 的__sum
已經變成了_Calc1__sum
,而 Calc2 的__sum
變成了_Calc2__sum
,所以各自類別裡的 __sum
不會產生衝突.
>>> class Calc1:
... __sum = 10
... def get_sum(self):
... return self.__sum
...
>>> class Calc2(Calc1):
... def add_sum(self,num):
... self.__sum = 2
... return self.get_sum() + num
...
既然__sum
已經改變所以用.__sum
當然找不到這屬性.
>>> c1 = Calc1()
>>> c1.__sum
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Calc1' object has no attribute '__sum'
必須使用下面的方式存取(_類別名稱__名稱
).
>>> c1._Calc1__sum
10
這時候呼叫可以發現self.get_sum()
取得就是 Calc1 的__sum
,答案就會是 10 + 5.
>>> c2 = Calc2()
>>> c2.add_sum(5)
15
>>> c2._Calc2__sum
2
最後整理一下 :
__名稱__
、_名稱
、名稱_
、__名稱
.今天為了介紹上面兩個觀念,範例其實還用到了模組跟子類別,後面的篇章再繼續介紹.