python訪問函數(shù)屬性 python 訪問

Python調(diào)用函數(shù)問題?

content是個(gè)Response對(duì)象的屬性 (有點(diǎn)類似變量), 而decode是bytes的一個(gè)方法

創(chuàng)新互聯(lián)是專業(yè)的萬榮網(wǎng)站建設(shè)公司,萬榮接單;提供成都網(wǎng)站建設(shè)、成都做網(wǎng)站,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行萬榮網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

方法在使用(調(diào)用/執(zhí)行)的時(shí)候是需要加括號(hào)的, 如果不加括號(hào)就會(huì)返回這個(gè)方法本身(類似函數(shù)指針), 而變量/成員字段/屬性是不能加括號(hào)的(除非它實(shí)現(xiàn)了__call__()方法)

python屬性訪問和方法調(diào)用是不是不一樣

首先,我們要明白,什么是屬性,什么是方法。下面看一個(gè)例子:

# -*- coding:utf8 -*-a = 1b = 2def func():

print 'func'

class example(object):

first = 1 # 定義變量 first

second = “two”

def myfunc(self): # 定義函數(shù)

print "myfunc."

上面的簡(jiǎn)單例子中,a和b是屬性么?不是,它們是全局變量(相對(duì)當(dāng)前例子而言)。func是方法么,不是,它是函數(shù)。

attribute(屬性)是class(類)中的成員變量,而method(方法)則是class(類)中的function(函數(shù))。也可以理解,屬性就類變量,方法就是類函數(shù)。那我們看看class example中的attribute。

dir(eaxmple)

不用奇怪為何myfunc也在其中,python一切皆為對(duì)象,dir(object)會(huì)返回當(dāng)前object的所有內(nèi)建方法,屬性等。

類中的變量就是靜態(tài)變量,類可以直接訪問,而方法則必須要綁定instance(實(shí)例)才可以訪問。請(qǐng)記住Python是一門動(dòng)態(tài)語言,任何實(shí)例都可以動(dòng)態(tài)地添加或刪除屬性。一個(gè)類定義了一個(gè)作用域,類實(shí)例也引入了一個(gè)作用域,這與對(duì)應(yīng)類定義的作用域是不同的。在類實(shí)例中查找屬性的時(shí)候,首先在實(shí)例自己的作用域中查找,如果沒有找到,則再去類定義的作用域中查找。在對(duì)類實(shí)例屬性進(jìn)行賦值的時(shí)候,實(shí)際上會(huì)在類實(shí)例定義的作用域中添加一個(gè)屬性或修改一個(gè)屬性,但并不會(huì)影響到對(duì)應(yīng)類中定義的同名屬性。

為了直觀的感受實(shí)例訪問屬性和方法調(diào)用都做了什么,我們對(duì)代碼進(jìn)行了如下修改。

class example(object):

first = 1 # 定義變量 first

second = "two"

def my_func(self): # 定義方法 my_func

print "This is my func."

def __getattribute__(self, *args, **kwargs):

print "__getattribute__ is called"

return object.__getattribute__(self, *args, **kwargs) def __getattr__(self, attrname):

print("__getattr__() is called ")

return attrname + " :This my exception deal."

def __setattr__(self, attrname, value):

print("__setattr__() is called")

return object.__setattr__(self, attrname, value)

首先,我們對(duì)類進(jìn)行實(shí)例化。

test = example()

我們先對(duì)屬性進(jìn)行訪問

看來實(shí)例test訪問屬性通過了內(nèi)建方法__getattribute__,那么我們?cè)賹?duì)訪問類方法

我們發(fā)現(xiàn)內(nèi)建方法__getattribute__再次被調(diào)用了。所以,實(shí)例訪問屬性和調(diào)用方法,是沒有區(qū)別的。

拓展

我們又重寫了__getattr__和__setattr__,那么這兩個(gè)是干什么的呢。

哦,原來對(duì)實(shí)例添加屬性并賦值的時(shí)候,會(huì)調(diào)用__setattr__,而訪問屬性,還是老方法。如果對(duì)沒有的屬性進(jìn)行訪問,就會(huì)拋出AttributeError,這時(shí)候,為了避免這種情況,__getattr__就派上了用處。

首先訪問屬性four,在實(shí)例作用域并沒有找到,再去對(duì)應(yīng)類的作用域,依然未找到,解釋器就會(huì)拋出AttributeError,這時(shí)候__getattr__就會(huì)調(diào)用(當(dāng)程序拋出Attribute時(shí)),這時(shí)候就會(huì)返回我們?cè)O(shè)置的默認(rèn)值。

Python的函數(shù)和參數(shù)

parameter 是函數(shù)定義的參數(shù)形式

argument 是函數(shù)調(diào)用時(shí)傳入的參數(shù)實(shí)體。

對(duì)于函數(shù)調(diào)用的傳參模式,一般有兩種:

此外,

也是關(guān)鍵字傳參

python的函數(shù)參數(shù)定義一般來說有五種: 位置和關(guān)鍵字參數(shù)混合 , 僅位置參數(shù) , 僅關(guān)鍵字參數(shù) , 可變位置參數(shù) , 可變關(guān)鍵字參數(shù) 。其中僅位置參數(shù)的方式僅僅是一個(gè)概念,python語法中暫時(shí)沒有這樣的設(shè)計(jì)。

通常我們見到的函數(shù)是位置和關(guān)鍵字混合的方式。

既可以用關(guān)鍵字又可以用位置調(diào)用

這種方式的定義只能使用關(guān)鍵字傳參的模式

f(*some_list) 與 f(arg1, arg2, ...) (其中some_list = [arg1, arg2, ...])是等價(jià)的

網(wǎng)絡(luò)模塊request的request方法的設(shè)計(jì)

多數(shù)的可選參數(shù)被設(shè)計(jì)成可變關(guān)鍵字參數(shù)

有多種方法能夠?yàn)楹瘮?shù)定義輸出:

非常晦澀

如果使用可變對(duì)象作為函數(shù)的默認(rèn)參數(shù),會(huì)導(dǎo)致默認(rèn)參數(shù)在所有的函數(shù)調(diào)用中被共享。

例子1:

addItem方法的data設(shè)計(jì)了一個(gè)默認(rèn)參數(shù),使用不當(dāng)會(huì)造成默認(rèn)參數(shù)被共享。

python里面,函數(shù)的默認(rèn)參數(shù)被存在__default__屬性中,這是一個(gè)元組類型

例子2:

在例子1中,默認(rèn)參數(shù)是一個(gè)列表,它是mutable的數(shù)據(jù)類型,當(dāng)它寫進(jìn) __defauts__屬性中時(shí),函數(shù)addItem的操作并不會(huì)改變它的id,相當(dāng)于 __defauts__只是保存了data的引用,對(duì)于它的內(nèi)存數(shù)據(jù)并不關(guān)心,每次調(diào)用addItem,都可以修改 addItem.__defauts__中的數(shù)據(jù),它是一個(gè)共享數(shù)據(jù)。

如果默認(rèn)參數(shù)是一個(gè)imutable類型,情況將會(huì)不一樣,你無法改變默認(rèn)參數(shù)第一次存入的值。

例子1中,連續(xù)調(diào)用addItem('world') 的結(jié)果會(huì)是

而不是期望的

Python中處理屬性的重要屬性和函數(shù)是什么

處理屬性的重要屬性和函數(shù)

1、特殊屬性

__class__:對(duì)象所屬類的引用(即obj.__class__和type(obj)的作用相同)。Python中的某些特殊方法比如 __getattr__,只在對(duì)象的類中尋找,而不在實(shí)例中尋找。__dict__:一個(gè)映射,存儲(chǔ)對(duì)象或類的可寫屬性。__slots__:類可以定義這個(gè)屬性,限制實(shí)例有哪些屬性。

2、內(nèi)置函數(shù)

dir([object]):列出對(duì)象的大多數(shù)屬性。getattr(object,name[,default]):從object對(duì)象中獲取name字符串對(duì)應(yīng)的屬性。獲取的屬性可能來自對(duì)象所屬的類或超類。hasattr(object,name):若object對(duì)象中存在指定的屬性,或者能以某種方式(如繼承)通過object對(duì)象獲取指定的屬性,返回True。setattr(object,name,value):把object對(duì)象指定屬性的值設(shè)為value,前提是object對(duì)象能接受那個(gè)值。這個(gè)函數(shù)可能會(huì)創(chuàng)建一個(gè)新屬性,或者覆蓋現(xiàn)有的屬性。var([object]):返回object對(duì)象的__dict__屬性。

相關(guān)推薦:《Python視頻教程》

3、特殊方法

__delattr__(self,name):只要使用del語句刪除屬性,就會(huì)調(diào)用這個(gè)方法。__dir__(self):把對(duì)象傳給dir函數(shù)時(shí)調(diào)用,列出屬性。__getattr__(self,name):僅當(dāng)獲取指定的屬性失敗,搜索過obj,Class和超類之后調(diào)用。__getattribute__(self,name):嘗試獲取指定的屬性時(shí)總會(huì)調(diào)用這個(gè)方法。不過尋找的屬性是特殊屬性或特殊方法時(shí)除外。為了防止無限遞歸,__getattribute__方法的實(shí)現(xiàn)要使用super().__getattribute__(obj,name)。__setattr__(self,name,value):嘗試設(shè)置指定的屬性時(shí)總會(huì)調(diào)用這個(gè)方法。點(diǎn)號(hào)和setattr內(nèi)置函數(shù)會(huì)觸發(fā)這個(gè)方法。

相關(guān)推薦:

Python中的屬性和特性是什么

如何正確地使用Python的屬性和描述符

關(guān)于@property裝飾器

在Python中我們使用@property裝飾器來把對(duì)函數(shù)的調(diào)用偽裝成對(duì)屬性的訪問。

那么為什么要這樣做呢?因?yàn)锧property讓我們將自定義的代碼同變量的訪問/設(shè)定聯(lián)系在了一起,同時(shí)為你的類保持一個(gè)簡(jiǎn)單的訪問屬性的接口。

舉個(gè)栗子,假如我們有一個(gè)需要表示電影的類:

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

你開始在項(xiàng)目的其他地方使用這個(gè)類,但是之后你意識(shí)到:如果不小心給電影打了負(fù)分怎么辦?你覺得這是錯(cuò)誤的行為,希望Movie類可以阻止這個(gè)錯(cuò)誤。 你首先想到的辦法是將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

但這行不通。因?yàn)槠渌糠值拇a都是直接通過Movie.score來賦值的。這個(gè)新修改的類只會(huì)在__init__方法中捕獲錯(cuò)誤的數(shù)據(jù),但對(duì)于已經(jīng)存在的類實(shí)例就無能為力了。如果有人試著運(yùn)行m.scrore= -100,那么誰也沒法阻止。那該怎么辦?

Python的property解決了這個(gè)問題。

我們可以這樣做

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都會(huì)檢測(cè)它是否小于0。

property的不足

對(duì)property來說,最大的缺點(diǎn)就是它們不能重復(fù)使用。舉個(gè)例子,假設(shè)你想為ticket字段也添加非負(fù)檢查。下面是修改過的新類:

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")

可以看到代碼增加了不少,但重復(fù)的邏輯也出現(xiàn)了不少。雖然property可以讓類從外部看起來接口整潔漂亮,但是卻做不到內(nèi)部同樣整潔漂亮。

描述符登場(chǎng)

什么是描述符?

一般來說,描述符是一個(gè)具有綁定行為的對(duì)象屬性,其屬性的訪問被描述符協(xié)議方法覆寫。這些方法是__get__()、__set__()和__delete__(),一個(gè)對(duì)象中只要包含了這三個(gè)方法中的至少一個(gè)就稱它為描述符。

描述符有什么作用?

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.—–摘自官方文檔

簡(jiǎn)單的說描述符會(huì)改變一個(gè)屬性的基本的獲取、設(shè)置和刪除方式。

先看如何用描述符來解決上面 property邏輯重復(fù)的問題。

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')

因?yàn)槊枋龇麅?yōu)先級(jí)高并且會(huì)改變默認(rèn)的get、set行為,這樣一來,當(dāng)我們?cè)L問或者設(shè)置Movie().score的時(shí)候都會(huì)受到描述符Integer的限制。

不過我們也總不能用下面這樣的方式來創(chuàng)建實(shí)例。

a = Movie()

a.score = 1

a.ticket = 2

a.title = ‘test’

a.descript = ‘…’

這樣太生硬了,所以我們還缺一個(gè)構(gòu)造函數(shù)。

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

這樣在獲取、設(shè)置和刪除score和ticket的時(shí)候都會(huì)進(jìn)入Integer的__get__、__set__,從而減少了重復(fù)的邏輯。

現(xiàn)在雖然問題得到了解決,但是你可能會(huì)好奇這個(gè)描述符到底是如何工作的。具體來說,在__init__函數(shù)里訪問的是自己的self.score和self.ticket,怎么和類屬性score和ticket關(guān)聯(lián)起來的?

描述符如何工作

看官方的說明

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.

類調(diào)用__getattribute__()的時(shí)候大概是下面這樣子:

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

下面是摘自國外一篇博客上的內(nèi)容。

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__.

我對(duì)上面的理解是,訪問一個(gè)實(shí)例的屬性的時(shí)候是先遍歷它和它的父類,尋找它們的__dict__里是否有同名的data descriptor如果有,就用這個(gè)data descriptor代理該屬性,如果沒有再尋找該實(shí)例自身的__dict__,如果有就返回。任然沒有再查找它和它父類里的non-data descriptor,最后查找是否有__getattr__

描述符的應(yīng)用場(chǎng)景

python的property、classmethod修飾器本身也是一個(gè)描述符,甚至普通的函數(shù)也是描述符(non-data discriptor)

django model和SQLAlchemy里也有描述符的應(yīng)用

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

后記

只有當(dāng)確實(shí)需要在訪問屬性的時(shí)候完成一些額外的處理任務(wù)時(shí),才應(yīng)該使用property。不然代碼反而會(huì)變得更加啰嗦,而且這樣會(huì)讓程序變慢很多。

python怎么查看函數(shù)有什么參數(shù)

在開發(fā)中我們可以借助于相關(guān)插件或使用Python內(nèi)置函數(shù)"help()”來查看某個(gè)函數(shù)的參數(shù)說明,以查看內(nèi)置函數(shù)sorted()為例:

函數(shù)參數(shù)包括:必選參數(shù)、默認(rèn)參數(shù)、可選參數(shù)、關(guān)鍵字參數(shù)。

1、默認(rèn)參數(shù):放在必選參數(shù)之后,計(jì)算x平方的函數(shù):

這樣的話每次計(jì)算不同冪函數(shù)都要重寫函數(shù),非常麻煩,可使用以下代碼計(jì)算:

默認(rèn)參數(shù)最大好處就是降低調(diào)用函數(shù)的難度。

2、可變參數(shù):就是傳入的參數(shù)個(gè)數(shù)是可變的,可以是1個(gè)、2個(gè)到任意個(gè),還可以是0個(gè),在參數(shù)前面加上*就是可變參數(shù)。在函數(shù)內(nèi)部,參數(shù)numbers接收得到的是一個(gè)tuple,調(diào)用該函數(shù)時(shí),可以傳入任意個(gè)參數(shù),包括0個(gè)參數(shù):

也可以類似可變參數(shù),先組裝一個(gè)dict,然后,把該dict轉(zhuǎn)換為關(guān)鍵字參數(shù)傳進(jìn)去:

本文名稱:python訪問函數(shù)屬性 python 訪問
網(wǎng)頁URL:http://muchs.cn/article22/doschjc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、營銷型網(wǎng)站建設(shè)域名注冊(cè)、網(wǎng)站設(shè)計(jì)公司、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)