㈠ python中類屬性和實例屬性的區別
今天一同事說踩了python的坑,
這確實是個「坑」
但是我覺得python之所以這樣設計,就是明確要求寫代碼的人知道自己在寫什麼^
^
python的實例屬性必須在__init__(self)
方法中定義,直接跟在類名後邊定義的屬性都默認是類屬性(類似於c++的static變數)。
而python實例又可以靈活的隨便增加屬性,便出現了圖片中看似詭異的現象。
---------------------------------
我們來看一下他的原代碼:
你覺得輸出會是什麼?
結果是
model_path
分別是
"xx_model"
和
"oo_model"
而model_dict全都是第二次調用的結果,也就是oo_model生成的dict的值(注意,他前邊有一句self.model_dict.clear()
)
原因是什麼呢?
"坑"
就在
他是用self.xxxx
這種方式引用變數,而不是self.__class__.xxxx
(1)
self.model_path=path;
#這對self.model_path進行了賦值,python中的第一次賦值視為變數的定義!
(2)
self.xxxx這種格式的第一次賦值含義是什麼呢?-->含義是:定義,也就是說定義了一個名為xxxx的實例屬性。
(3)
因此m1,m2的兩次調用,分別定義了對應的(不同的)self.model_path屬性。
而self.model_dict,從頭到尾都是
引用
它,從未進行過
賦值(重定義),所以引用的都是
類屬性
㈡ 編程語言python的類(class)的問題
很不想跟你說, 你思維一片混亂. 根本不適合寫程序.
先搞清楚類和對象的區別再說吧.
-----------------------------------
你的態度很好, 我的態度不好,我道歉.
1 類和對象是兩種不同的概念, 類是一個抽象的定義, 對象是一個實際的實體. 我不想抄書, 舉個例子, "人"是一個類. "某人"就是一個對象
對於你的問題, Liste是一個類, i.first裡面的這個i,就是一個對象(稱為Liste對象)。 i.first=n,表示修改了i這個對象的first屬性。 如果還有其它Liste對象, 這些對象的first值並不與i的first相關。
然後, 你說的class的屬性的初始值,這個說法並不精確。 因為 first屬性是在__init__方法中定義的, 而__init__方法是初始化任意一個Liste對象時都要調用的方法。因此你理解他為初始值。但是實際上, __init__方法給屬性賦值,與你在外面一個函數給這個屬性賦值沒有大區別。
因此,我這樣總結一下, 比如, 你聲明了兩個Liste對象 i=Liste() j=Liste(), 然後讓i.first=n, 之後, j.first還是依舊等於None, 然後,你又聲明了一個Liste對象, k=Liste(), k.first還是等於None
2 當你定義了一個類, 之後要創建一個這個類的對象, 我們用的方示就是
n=Node(x), 在這里類的名字當成一個函數來用, 而這個函數的參數x, 傳遞進入 None類的 __init__方法中去,也就是def __init__(self, x):這個方法。 因此n 就是一個Node對象,你看到print出來的內容就是表示n是一個None對象, 而其儲存地址是0x0....
3 你的理解是對的。
我建議你學習編程, 還是要從C或者Pascal學起, 把最基本的理論都搞清楚以後,然後再學習C++,弄明白面向對象,最後再學習python, 循序漸進對於打好扎實的基礎是很重要的。
㈢ python類的屬性有哪幾種如何訪問它們
屬性的訪問機制
一般情況下,屬性訪問的默認行為是從對象的字典中獲取,並當獲取不到時會沿著一定的查找鏈進行查找。例如a.x的查找鏈就是,從a.__dict__['x'],然後是type(a).__dict__['x'],再通過type(a)的基類開始查找。
若查找鏈都獲取不到屬性,則拋出AttributeError異常。
一、__getattr__方法
這個方法是當對象的屬性不存在是調用。如果通過正常的機制能找到對象屬性的話,不會調用__getattr__方法。
classA:
a=1
def__getattr__(self,item):
print('__getattr__call')
returnitem
t=A()
print(t.a)
print(t.b)
#output
1
__getattr__call
b
二、__getattribute__方法
這個方法會被無條件調用。不管屬性存不存在。如果類中還定義了__getattr__,則不會調用__getattr__()方法,除非在__getattribute__方法中顯示調用__getattr__()或者拋出了AttributeError。
classA:
a=1
def__getattribute__(self,item):
print('__getattribute__call')
raiseAttributeError
def__getattr__(self,item):
print('__getattr__call')
returnitem
t=A()
print(t.a)
print(t.b)
所以一般情況下,為了保留__getattr__的作用,__getattribute__()方法中一般返回父類的同名方法:
def__getattribute__(self,item):
returnobject.__getattribute__(self,item)
使用基類的方法來獲取屬性能避免在方法中出現無限遞歸的情況。
三、__get__方法
這個方法比較簡單說明,它與前面的關系不大。
如果一個類中定義了__get__(),__set__()或__delete__()中的任何方法。則這個類的對象稱為描述符。
classDescri(object):
def__get__(self,obj,type=None):
print("callget")
def__set__(self,obj,value):
print("callset")
classA(object):
x=Descri()
a=A()
a.__dict__['x']=1#不會調用__get__
a.x#調用__get__
如果查找的屬性是在描述符對象中,則這個描述符會覆蓋上文說的屬性訪問機制,體現在查找鏈的不同,而這個行文也會因為調用的不同而稍有不一樣:
其他情況見文末參考資料的文檔
四、__getitem__方法
如果僅僅想要對象能夠通過[]獲取對象屬性可以簡單的:
總結
當這幾個方法同時出現可能就會擾亂你了。我在網上看到一份示例還不錯,稍微改了下:
㈣ Python中的類屬性和對象屬性的區別詳解
類屬性:
class Employee(object):
emCount=0
def __init__(self,name,salary):
self.nane=name
self.salary=salary
類屬性就是定義類的時候直接定義的屬性 emCount,類似於java裡面的static修飾的屬性,可以直接通過 類名.屬性名訪問:Employee.emCount
實例屬性是在__init()方法中定義的屬性,例如name,和salary,self是指向自己的,類似java的this關鍵字,實際是通過內置的方法setattr()完成的
可以通過重寫setatttr()進行類屬性的增加和獲取
㈤ python中class自賦屬性值的使用問題
self.start = start#為什麼要設定這么一個屬性值start
舉例:
g=Game(start=2)
print(g.start)#不設定那個屬性值的話,這句就會報錯
room = getattr(self, next) #這個地方怎麼理解room該取得的值呢?為什麼會用到next?為什麼實際用到了屬性值start
這句在該例中 相當於room=getattr(self, "tsroom"),也即room=self.tsroom
至於怎麼理解,這個很難講的請,只能說你了解語法之後,再自個兒琢磨琢磨。
㈥ python類的定義與使用是什麼
類Class:用來描述具體相同的屬性和方法的對象的集合。定義了該集合中每個對象所共有的屬性和方法。對象是類的示例。
類定義完成時(正常退出),就創建了一個 類對象。基本上它是對類定義創建的命名空間進行了一個包裝;我們在下一節進一步學習類對象的知識。原始的局部作用域(類定義引入之前生效的那個)得到恢復,類對象在這里綁定到類定義頭部的類名(例子中是 ClassName )。
基本語法
Python的設計目標之一是讓代碼具備高度的可閱讀性。它設計時盡量使用其它語言經常使用的標點符號和英文單字,讓代碼看起來整潔美觀。它不像其他的靜態語言如C、Pascal那樣需要重復書寫聲明語句,也不像它們的語法那樣經常有特殊情況和意外。
以上內容參考:網路-Python
㈦ 談談python中類屬性和類實例的屬性的區別
一般來說,在Python中,類實例屬性的訪問規則算是比較直觀的。
但是,仍然存在一些不是很直觀的地方,特別是對C++和Java程序員來說,更是如此。
在這里,我們需要明白以下幾個地方:
1.Python是一門動態語言,任何實體都可以動態地添加或刪除屬性。
2.一個類定義了一個作用域。
3.類實例也引入了一個作用域,這與相應類定義的作用域不同。
4.在類實例中查找屬性的時候,首先在實例自己的作用域中查找,如果沒有找到,則再在類定義的作用域中查找。
5.在對類實例屬性進行賦值的時候,實際上會在類實例定義的作用域中添加一個屬性(如果還不存在的話),並不會影響到相應類中定義的同名屬性。
下面看一個例子,加深對上述幾點的理解:
復制代碼
代碼如下:
class A:
cls_i = 0
cls_j
= {}
def __init__(self):
self.instance_i =
0
self.instance_j =
{}
在這里,我們先定義類A的一個實例a,然後再看看類A的作用域和實例a的作用域中分別有什麼:
復制代碼
代碼如下:
>>> a = A()
>>>
a.__dict__
{'instance_j': {}, 'instance_i': 0}
>>>
A.__dict__
{'__init__': , '__mole__': '__main__', 'cls_i': 0, 'cls_j': {},
'__doc__': None}
我們看到,a的作用域中有instance_i和instance_j,A的作用域中有cls_i和cls_j。
我們再來看看名字查找是如何發生的:
復制代碼
代碼如下:
>>> a.cls_i
0
>>>
a.instance_i
0
在查找cls_i的時候,實例a的作用域中是沒有它的,卻在A的作用域中找到了它;在查找instance_i的時候,直接可在a的作用域中找到它。
如果我們企圖通過實例a來修改cls_i的值,那會怎樣呢:
復制代碼
代碼如下:
>>> a.cls_i = 1
>>>
a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}
>>>
A.__dict__
{'__init__': , '__mole__': '__main__', 'cls_i': 0, 'cls_j': {},
'__doc__': None}
我們可以看到,a的作用域中多了一個cls_i屬性,其值為1;同時,我們也注意到A作用域中的cls_i屬性的值仍然為0;在這里,我們其實是增加了一個實例屬性,並沒有修改到類屬性。
如果我們通過實例a操縱cls_j中的數據(注意不是cls_j本身),又會怎麼樣呢:
復制代碼
代碼如下:
>>> a.cls_j['a'] =
'a'
>>> a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i':
0}
>>> A.__dict__
{'__init__': , '__mole__': '__main__',
'cls_i': 0, 'cls_j': {'a': 'a'}, '__doc__': None}
我們可以看到a的作用域沒有發生什麼變化,但是A的作用域發生了一些變化,cls_j中的數據發生了變化。
實例的作用域發生變化,並不會影響到該類的其它實例,但是類的作用域發生變化,則會影響到該類的所有實例,包括在這之前創建的實例:
復制代碼
代碼如下:
>>> A.cls_k = 0
㈧ python 類裡面的class是什麼意思啊求
python這方面很靈活。其實java也一樣允許這樣子。你幾乎可以在任何情況下做任何事情。
通常class Meta可以放在外面。不過,這樣它就不能直接訪問父類的一些屬性了。
所以在python里class 如果放在另一個class 裡面,通常並不是為了隱藏這個class,並不是讓別人看不到它。而因為它需要父類里的一些屬性。需要共享。
另外直接在類里定義的一些變數,比如queryset,也是屬於類全局級的。只要引用了這個類,即使沒有初始化,這些變數也已經實例化。這個有些象是java里static的全局定義結果。
我們通常用這個方法來在不同的函數變數間共享 一部分數據。同時又不需要初始化一個實例並用指針指向這一部分數據。而是通過類名直接引用。
比如下面的一個用法
class Config:
pass
Config.user_name="xxx"
Config.password="yyyy"
這樣。只要你在當前模塊里,通過Config就可以引用到user_name和password,而不需要global這個修飾符。
㈨ python關於class的問題
對象構造後第一個調用的函數,在python裡面實例的屬性是可以動態構建的,在類裡面定義的屬性是類屬性,不是實例屬性,定義實例自己的屬性的最好地方是__init__函數裡面。
比如
class TEST():
class_attr #類屬性,通過TEST.class_attr調用,如果用instance.class_attr調用實際上是聲明類另一個實例屬性,與之前的TEST.class_attr不是一個東西了
def __init__(self,other):
self.class_attr #實例屬性,與之前的那個屬性處於不同的名字空間了,不是一個東西。
self.other=other
總之,__init__可以用來聲明實例屬性,以及進行必要的初始化。
希望能解決您的問題。
㈩ python關於class問題 小白求解答
Python編程中類的概念可以比作是某種類型集合的描述,如「人類」可以被看作一個類,然後用人類這個類定義出每個具體的人——你、我、他等作為其對象。類還擁有屬性和功能,屬性即類本身的一些特性,如人類有名字、身高和體重等屬性,而具體值則會根據每個人的不同;功能則是類所能實現的行為,如人類擁有吃飯、走路和睡覺等功能。具體的形式如下:
#例:類的概念
class人類:
名字='未命名'#成員變數
def說話(內容):#成員函數
print內容#成員變數賦初始值
某人=人類()#定義一個人類對象某人
某人.名字="路人甲"
某人.說話('大家好')#路人甲說話
>>>大家好!#輸出
Python中定義和使用類的形式為:class 類名[(父類名)]:[成員函數及成員變數],類名為這個類的名稱,而父類名為可選,但定義父類名後,子類則擁有父類的相應屬性和方法。在用類定義成對象時,會先調用__init__構造函數,以初始化對象的各屬性,類的各屬性(成員變數)均可以在構造函數中定義,定義時只要加上對象指針就好了。而在對象銷毀時,則會調用__del__析構函數,定義類的成員函數時,必須默認一個變數(類似於C++中的this指針)代表類定義的對象本身,這個變數的名稱可自行定義,下面例子將使用 self變數表示類對象變數 。
#例:類定義及使用
classCAnimal:
name='unname'#成員變數
def__init__(self,voice='hello'):#重載構造函數
self.voice=voice#創建成員變數並賦初始值
def__del__(self):#重載析構函數
pass#空操作
defSay(self):
printself.voice
t=CAnimal()#定義動物對象t
t.Say()#t說話
>>hello#輸出
dog=CAnimal('wow')#定義動物對象dog
dog.Say()#dog說話
>>wow#輸出