Python類的私有屬性與私有方法的使用


xx: 公有變量
_x: 單前置下划線,私有化屬性或方法,from somemodule import 禁止導入,類對象和子類可以訪問【另解:前置單下划線,又稱口頭私有變量,私有化屬性或方法的一種,一般來講,變量名_xx被看作是“私有 的”,在模塊或類外不可以使用。當變量是私有的時候,用_xx 來表示變量是很好的習慣。類對象和子類可以訪問,這並不能完全做到真正的私有,只是約定俗成的而已,這樣寫表示不希望這個變量在外部被直接調用】
__xx:雙前置下划線,避免與子類中的屬性命名沖突,無法在外部直接訪問(名字重整所以訪問不到)【__xx:前置雙下划線,私有化屬性或方法,只有內部可以訪問,外部不能訪問。】
__xx__:雙前后下划線,用戶名字空間的魔法對象或屬性。例如:init , __ 不要自己發明這樣的名字【__xx__:以雙下划線開頭,並且以雙下划線結尾的,是特殊變量(這就是在python中強大的魔法方法),特殊變量是可以直接訪問的,對於普通的變量應當避免這種命名風格。】
xx
:單后置下划線,用於避免與Python關鍵詞的沖突
通過name mangling(名字重整(目的就是以防子類意外重寫基類的方法或者屬性)如:_Class__object)機制就可以訪問private了。

#coding=utf-8

class Person(object):
    def __init__(self, name, age, taste):
        self.name = name
        self._age = age 
        self.__taste = taste

    def showperson(self):
        print(self.name)
        print(self._age)
        print(self.__taste)

    def dowork(self):
        self._work()
        self.__away()


    def _work(self):
        print('my _work')

    def __away(self):
        print('my __away')

class Student(Person):
    def construction(self, name, age, taste):
        self.name = name
        self._age = age 
        self.__taste = taste

    def showstudent(self):
        print(self.name)
        print(self._age)
        print(self.__taste)

    @staticmethod
    def testbug():
        _Bug.showbug()

# 模塊內可以訪問,當from  cur_module import *時,不導入
class _Bug(object):
    @staticmethod
    def showbug():
        print("showbug")

s1 = Student('jack', 25, 'football')
s1.showperson()
print('*'*20)

# 無法訪問__taste,導致報錯
# s1.showstudent() 
s1.construction('rose', 30, 'basketball')
s1.showperson()
print('*'*20)

s1.showstudent()
print('*'*20)

Student.testbug()

 

 

 

----------------------------------------------講解----------------------------------------------------------------------------------------

1.Python中屬性:類屬性 ,實例屬性,私有屬性的使用

在Python中的屬性分為:類屬性和對象(實例)屬性:

1.類屬性就是屬於類所有,可以直接用類名.屬性名直接調用,類的屬性在內存中只有一份。實例屬性就是在__init__()方法中初始化的屬性;
2.實例屬性屬於類的對象所有,可以用對象名.屬性名的形式進行調用,但是不能用類名.屬性名進行調用 。因為實例屬性只有在實例創建時,才會初始化創建。

#1.類屬性和實例的屬性的調用關系
class Person:
    country ="china"  #類屬性
    def __init__(self,name,age):
        sex =""   #這不是實例屬性,只是變量而已,用對象名.sex調不出來。
        self.name = name #實例屬性
        self.age = age
#創建對象
print(Person.country) 
#print(Person.age) 出錯,AttributeError: type object 'Person' has no attribute 'age'
p1 = Person("tom",12)
print(p1.country,p1.age,p1.name,p1)

----------結果如下------------------------------------------------------------------------
china
china 12 tom
----------------------------------------------------------------------------------------

#2.修改類屬性和實例屬性:類屬性只能通過類名.屬性才可以修改
class Person:
    country ="china"  #類屬性
    def __init__(self,name,age):
        sex =""   #這不是實例屬性,只是變量而已,用對象名.sex調不出來。
        self.name = name #實例屬性
        self.age = age
 
-------創建對象-------------------------------------------------------------------------
p1.country = "america"
print(p1.country) #通過實例去修改屬性,實例的屬性修改了:america
print(Person.country)#但是類的屬性還是沒有修改:china
 
Person.country = "japan" #只有用類名.屬性名才能修改類的屬性值。
p2= Person("jack",11)
print("p1.country:",p1.country) 
print("p2.country",p2.country)
print("Person.country",Person.country)
------結果如下-----------------------------------------------------------------------------
america
china
p1.country: america
p2.country japan
Person.country japan

實際開發中為了程序的安全,關於類的屬性都會封裝起來,Python中為了更好的保存屬性安全,即不能隨意修改。一般屬性的處理方式為:1.將屬性定義為私有屬性。2.添加一個可以調用的方法,供調用。

3.Python中用__兩個下划線開頭,聲明該屬性為私有,不能在類地外部被使用或直接訪問

class Person1(object):
    country ='china' #類屬性
    __language ="Chinese" #私有類屬性也不能直接外部調用
    def __init__(self,name,age):
        self.name = name
        self.__age = age  #使用__下划線表示私有屬性,對象不能直接調用,要通過方法調調用
 
    def getAge(self):
        return self.__age
 
    def setAge(self,age):
        if age >100 or age <0:
            print("age is not true")
        else :
            self.__age = age
 
    def __str__(self):
        info = "name :"+self.name +",age(保密):"+str(self.__age)  #注意這里不是self.age
        return info
 
#------創建對象,調用方法,屬性測試-------------------------------------------------------
stu1 =  Person1("tom",18)
print("修改前的結果:",stu1.__str__())
stu1.name="tom_2"  #修改stu1的name屬性
print("修改name后的結果:",stu1.__str__())
#print(stu1.__age)  #直接調用私有屬性__age報錯,'Person1' object has no attribute '__age'
 
print("打印私有age內存地址:",id(stu1.getAge()))
stu1.__age = 19  #如果這樣賦值的話,不會報錯,因為系統找不到這個變量,直接新建了一個。但是實際沒有修改對象的屬性值
print(stu1.__age) #有值,但是沒有 實際修改stu1對象的age屬性值
print("打印stu1.__age的內存地:",id(stu1.__age)) #兩個內存地址值不一樣。
print("錯誤修改age后的值",stu1.__str__())  #實際值沒有變
 
stu1.setAge(22) #只有調用才可以修改age的值
print("正確修改age后的值",stu1.__str__())
 
'''執行結果如下:
修改前的結果: name :tom,age(保密):18
修改name后的結果: name :tom_2,age(保密):18
打印私有age內存地址: 1388146224
19
打印stu1.__age的內存地: 1388146256
錯誤修改age后的值 name :tom_2,age(保密):18
正確修改age后的值 name :tom_2,age(保密):22
'''

2.私有方法,類方法,靜態方法的使用

1.私有方法:以 __兩個下划線開頭,聲明該方法為私有方法,只能在類的內部調用 (類內部別的方法可以調用他),不能在類地外部調用。

lass Person5:
 
    def __p(self):
        print("這是私有屬性") #內部函數也同樣可以任意之間互相調用
    def p1(self):
        print("這是p1不是私有方法")
    def p2(self):
        print("這是p2,可以調用p1,也可以調用私有方法__p")
        self.p1()
        self.__p()
#創建對象
c1 = Person5()
c1.p1()
c1.p2()
#c1.__p() #不能直接私有函數。報錯。注意區分系統自帶的函數如__str__,外部可以直接調用的。
 
'''結果如下:
這是p1不是私有方法
這是p2,可以調用p1,也可以調用私有方法__p
這是p1不是私有方法
這是私有屬性
'''

2.類方法的使用:是類所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對於類方法,第一個參數必須是類對象,一般以cls作為第一個參數,也可以有別的參數。但是第一個必須是類對象,類似類中的def定義的普通方法第一個參數要是self一樣的道理

class People(object):
    country = 'china'
 
    #類方法,用classmethod來進行修飾,跟普通的方法區別就是可以直接通過類名.方法名的方式調用
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def sum(cls,a,b):
        return a+b        
 
p = People()
print (p.getCountry())  #可以用過實例對象引用
print (People.getCountry() )   #可以通過類名.方法名的形式調用
print(p.sum(10,11))  
print(People.sum(10,11))
====================================================================================
china
china
21
21
3.靜態方法:需要通過修飾器@staticmethod來進行修飾,靜態方法不需要多定義參數 

class People(object):
    country = 'china'
 
    @staticmethod
    #靜態方法,不用定義參數
    def getCountry():
        return People.country
 
 
print (People.getCountry())

3.方法的使用注意要點
注意python中不支持方法的重載:即方法名相同,參數類型(參數個數不同)不同的函數,python中 不支持。

def p():
    print("dd")
def p(a,b):
    print("dd")
 
def p(a):
    print("dd")
p()#報錯,因為python中不需要定義參數的類型。如果有多個重載的函數,則python默認只能使用最后一個有效。
所以只能調用P(a)這個函數

 



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM