① python方法中的屬性,實例可否直接調用
"方法中的屬性"這個說法有點不清楚。。
類的"屬性"指的是類的成員變數,類的實例可以使用類的屬性。
類的「方法」指的是類的成員函數;方法既可以調用類的屬性,也可以定義自己的局部變數。方法的局部變數不能被方法以外的任何函數調用。
② python模型的屬性調用不出來怎麼辦
可以通過setatter給元素添加屬性。
python提示對象沒有屬性需要給對象建立屬性,並且創建屬性的get和set方法進行取值和賦值。
③ python調用方法內部屬性
__xxxitem__:使用 [''] 的方式操作屬性時被調用
__setitem__:每當屬性被賦值的時候都會調用該方法,因此不能再該方法內賦值 self.name = value 會死循環
__getitem__:當訪問不存在的屬性時會調用該方法
__delitem__:當刪除屬性時調用該方法
④ python 里的屬性是什麼意思
Python是面向對象的語言,在python中一切皆對象
對象就是你要腳本或程序中的變數、類、函數。。。
每個對象有自己的屬性,比如一個函數有自己的形參、邏輯運算之類的。
類這個概念和C中的結構體差不多,就是定義一組對象,有一個固定的屬性,然後將類實例化,就是繼承這個類的所有屬性。
方法其實就是函數,你處理對象用的手段。
⑤ python怎麼使用 父類非常init方法下的屬性
那幾個變數你應該定義成self.格式的,
下面就可以直接引用了啊。
⑥ python 繼承與類屬性的使用
題主的注釋是沒有問題的。
子類繼承父類後,會自動繼承了父類的屬性。如果在子類中修改了繼承得來的類屬性時(即B.count=200),並不會修改父類的對應的同名類屬性(A.count)。以後只要是通過子類訪問該屬性,訪問的都是子類的屬性。
通過父類修改了父類屬性後,子類訪問該屬性時,會訪問父類修改後的屬性值。當然前提是子類沒有對該屬性重新賦值過。
⑦ Python中處理屬性的重要屬性和函數是什麼
處理屬性的重要屬性和函數
1、特殊屬性
__class__:對象所屬類的引用(即obj.__class__和type(obj)的作用相同)。Python中的某些特殊方法比如 __getattr__,只在對象的類中尋找,而不在實例中尋找。__dict__:一個映射,存儲對象或類的可寫屬性。__slots__:類可以定義這個屬性,限制實例有哪些屬性。
2、內置函數
dir([object]):列出對象的大多數屬性。getattr(object,name[,default]):從object對象中獲取name字元串對應的屬性。獲取的屬性可能來自對象所屬的類或超類。hasattr(object,name):若object對象中存在指定的屬性,或者能以某種方式(如繼承)通過object對象獲取指定的屬性,返回True。setattr(object,name,value):把object對象指定屬性的值設為value,前提是object對象能接受那個值。這個函數可能會創建一個新屬性,或者覆蓋現有的屬性。var([object]):返回object對象的__dict__屬性。
相關推薦:《Python視頻教程》
3、特殊方法
__delattr__(self,name):只要使用del語句刪除屬性,就會調用這個方法。__dir__(self):把對象傳給dir函數時調用,列出屬性。__getattr__(self,name):僅當獲取指定的屬性失敗,搜索過obj,Class和超類之後調用。__getattribute__(self,name):嘗試獲取指定的屬性時總會調用這個方法。不過尋找的屬性是特殊屬性或特殊方法時除外。為了防止無限遞歸,__getattribute__方法的實現要使用super().__getattribute__(obj,name)。__setattr__(self,name,value):嘗試設置指定的屬性時總會調用這個方法。點號和setattr內置函數會觸發這個方法。
相關推薦:
Python中的屬性和特性是什麼
⑧ 關於python動態添加屬性和方法的意義
通過對象的實例,在外部為其添加屬性,這種做法應該是很少見的。原因很簡單:破壞封裝。雖然Python可以做到,但並不代表隨意使用這種做法是妥當的。
添加的屬性可以和原有的組合使用的,有回答已經給出了例子。
我覺得有必要提一下self或者說方法的第一個參數是什麼。
需要注意的是,通過實例為類屬性賦值[7],會「遮蓋」類屬性。即,賦值只是為實例的屬性賦值,而未改動類的屬性。需要改動類屬性的話,應該使用類名的方式。
感興趣的話可以查查Python的Mixin,這是通過動態繼承添加屬性和方法的做法。
⑨ 如何正確地使用Python的屬性和描述符
關於@property裝飾器
在Python中我們使用@property裝飾器來把對函數的調用偽裝成對屬性的訪問。
那麼為什麼要這樣做呢?因為@property讓我們將自定義的代碼同變數的訪問/設定聯系在了一起,同時為你的類保持一個簡單的訪問屬性的介面。
舉個栗子,假如我們有一個需要表示電影的類:
1
2
3
4
5
6
7
8
class Movie(object):
def __init__(self, title, description, score, ticket):
self.title = title
self.description = description
self.score = scroe
self.ticket = ticket
你開始在項目的其他地方使用這個類,但是之後你意識到:如果不小心給電影打了負分怎麼辦?你覺得這是錯誤的行為,希望Movie類可以阻止這個錯誤。 你首先想到的辦法是將Movie類修改為這樣:
Python
1
2
3
4
5
6
7
8
class Movie(object):
def __init__(self, title, description, score, ticket):
self.title = title
self.description = description
self.ticket = ticket
if score < 0:
raise ValueError("Negative value not allowed:{}".format(score))
self.score = scroe
但這行不通。因為其他部分的代碼都是直接通過Movie.score來賦值的。這個新修改的類只會在__init__方法中捕獲錯誤的數據,但對於已經存在的類實例就無能為力了。如果有人試著運行m.scrore= -100,那麼誰也沒法阻止。那該怎麼辦?
Python的property解決了這個問題。
我們可以這樣做
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Movie(object):
def __init__(self, title, description, score):
self.title = title
self.description = description
self.score = score
self.ticket = ticket
@property
def score(self):
return self.__score
@score.setter
def score(self, score):
if score < 0:
raise ValueError("Negative value not allowed:{}".format(score))
self.__score = score
@score.deleter
def score(self):
raise AttributeError("Can not delete score")
這樣在任何地方修改score都會檢測它是否小於0。
property的不足
對property來說,最大的缺點就是它們不能重復使用。舉個例子,假設你想為ticket欄位也添加非負檢查。下面是修改過的新類:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Movie(object):
def __init__(self, title, description, score, ticket):
self.title = title
self.description = description
self.score = score
self.ticket = ticket
@property
def score(self):
return self.__score
@score.setter
def score(self, score):
if score < 0:
raise ValueError("Negative value not allowed:{}".format(score))
self.__score = score
@score.deleter
def score(self):
raise AttributeError("Can not delete score")
@property
def ticket(self):
return self.__ticket
@ticket.setter
def ticket(self, ticket):
if ticket < 0:
raise ValueError("Negative value not allowed:{}".format(ticket))
self.__ticket = ticket
@ticket.deleter
def ticket(self):
raise AttributeError("Can not delete ticket")
可以看到代碼增加了不少,但重復的邏輯也出現了不少。雖然property可以讓類從外部看起來介面整潔漂亮,但是卻做不到內部同樣整潔漂亮。
描述符登場
什麼是描述符?
一般來說,描述符是一個具有綁定行為的對象屬性,其屬性的訪問被描述符協議方法覆寫。這些方法是__get__()、__set__()和__delete__(),一個對象中只要包含了這三個方法中的至少一個就稱它為描述符。
描述符有什麼作用?
The default behavior for attribute access is to get, set, or delete the attribute from an object』s dictionary. For instance, a.x has a lookup chain starting witha.__dict__[『x』], then type(a).__dict__[『x』], and continuing through the base classes of type(a) excluding metaclasses. If the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined.—–摘自官方文檔
簡單的說描述符會改變一個屬性的基本的獲取、設置和刪除方式。
先看如何用描述符來解決上面 property邏輯重復的問題。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Integer(object):
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
if value < 0:
raise ValueError("Negative value not allowed")
instance.__dict__[self.name] = value
class Movie(object):
score = Integer('score')
ticket = Integer('ticket')
因為描述符優先順序高並且會改變默認的get、set行為,這樣一來,當我們訪問或者設置Movie().score的時候都會受到描述符Integer的限制。
不過我們也總不能用下面這樣的方式來創建實例。
a = Movie()
a.score = 1
a.ticket = 2
a.title = 『test』
a.descript = 『…』
這樣太生硬了,所以我們還缺一個構造函數。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Integer(object):
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
if value < 0:
raise ValueError('Negative value not allowed')
instance.__dict__[self.name] = value
class Movie(object):
score = Integer('score')
ticket = Integer('ticket')
def __init__(self, title, description, score, ticket):
self.title = title
self.description = description
self.score = score
self.ticket = ticket
這樣在獲取、設置和刪除score和ticket的時候都會進入Integer的__get__、__set__,從而減少了重復的邏輯。
現在雖然問題得到了解決,但是你可能會好奇這個描述符到底是如何工作的。具體來說,在__init__函數里訪問的是自己的self.score和self.ticket,怎麼和類屬性score和ticket關聯起來的?
描述符如何工作
看官方的說明
If an object defines both __get__() and __set__(), it is considered a data descriptor. Descriptors that only define __get__() are called non-data descriptors (they are typically used for methods but other uses are possible).
Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance』s dictionary. If an instance』s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance』s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.
The important points to remember are:
descriptors are invoked by the __getattribute__() method
overriding __getattribute__() prevents automatic descriptor calls
object.__getattribute__() and type.__getattribute__() make different calls to __get__().
data descriptors always override instance dictionaries.
non-data descriptors may be overridden by instance dictionaries.
類調用__getattribute__()的時候大概是下面這樣子:
1
2
3
4
5
6
7
def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v
下面是摘自國外一篇博客上的內容。
Given a Class 「C」 and an Instance 「c」 where 「c = C(…)」, calling 「c.name」 means looking up an Attribute 「name」 on the Instance 「c」 like this:
Get the Class from Instance
Call the Class』s special method getattribute__. All objects have a default __getattribute
Inside getattribute
Get the Class』s mro as ClassParents
For each ClassParent in ClassParents
If the Attribute is in the ClassParent』s dict
If is a data descriptor
Return the result from calling the data descriptor』s special method __get__()
Break the for each (do not continue searching the same Attribute any further)
If the Attribute is in Instance』s dict
Return the value as it is (even if the value is a data descriptor)
For each ClassParent in ClassParents
If the Attribute is in the ClassParent』s dict
If is a non-data descriptor
Return the result from calling the non-data descriptor』s special method __get__()
If it is NOT a descriptor
Return the value
If Class has the special method getattr
Return the result from calling the Class』s special method__getattr__.
我對上面的理解是,訪問一個實例的屬性的時候是先遍歷它和它的父類,尋找它們的__dict__里是否有同名的data descriptor如果有,就用這個data descriptor代理該屬性,如果沒有再尋找該實例自身的__dict__,如果有就返回。任然沒有再查找它和它父類里的non-data descriptor,最後查找是否有__getattr__
描述符的應用場景
python的property、classmethod修飾器本身也是一個描述符,甚至普通的函數也是描述符(non-data discriptor)
django model和SQLAlchemy里也有描述符的應用
Python
1
2
3
4
5
6
7
8
9
10
11
12
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
後記
只有當確實需要在訪問屬性的時候完成一些額外的處理任務時,才應該使用property。不然代碼反而會變得更加啰嗦,而且這樣會讓程序變慢很多。
⑩ 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__方法
如果僅僅想要對象能夠通過[]獲取對象屬性可以簡單的:
總結
當這幾個方法同時出現可能就會擾亂你了。我在網上看到一份示例還不錯,稍微改了下: