⑴ python對象
眾所周知,Python是一門面向對象的語言,在Python無論是數值、字元串、函數亦或是類型、類,都是對象。
對象是在 堆 上分配的結構,我們定義的所有變數、函數等,都存儲於堆內存,而變數名、函數名則是一個存儲於 棧 中、指向堆中具體結構的引用。
要想深入學習Python,首先需要知道Python對象的定義。
我們通常說的Python都是指CPython,底層由C語言實現,源碼地址: cpython [GitHub]
Python對象的定義位於 Include/object.h ,是一個名為 PyObject 的結構體:
Python中的所有對象都繼承自PyObejct,PyObject包含一個用於垃圾回收的雙向鏈表,一個引用計數變數 ob_refcnt 和 一個類型對象指針 ob_type
從PyObejct的注釋中,我們可以看到這樣一句:每個指向 可變大小Python對象 的指針也可以轉換為 PyVarObject* (可變大小的Python對象會在下文中解釋)。 PyVarObejct 就是在PyObject的基礎上多了一個 ob_size 欄位,用於存儲元素個數:
在PyObject結構中,還有一個類型對象指針 ob_type ,用於表示Python對象是什麼類型,定義Python對象類型的是一個 PyTypeObject 介面體
實際定義是位於 Include/cpython/object.h 的 _typeobject :
在這個類型對象中,不僅包含了對象的類型,還包含了如分配內存大小、對象標准操作等信息,主要分為:
以Python中的 int類型 為例,int類型對象的定義如下:
從PyObject的定義中我們知道,每個對象的 ob_type 都要指向一個具體的類型對象,比如一個數值型對象 100 ,它的ob_type會指向 int類型對象PyLong_Type 。
PyTypeObject結構體第一行是一個PyObject_VAR_HEAD宏,查看宏定義可知PyTypeObject是一個變長對象
也就是說,歸根結底 類型對象也是一個對象 ,也有ob_type屬性,那 PyLong_Type 的 ob_type 是什麼呢?
回到PyLong_Type的定義,第一行 PyVarObject_HEAD_INIT(&PyType_Type, 0) ,查看對應的宏定義
由以上關系可以知道, PyVarObject_HEAD_INIT(&PyType_Type, 0) = { { _PyObject_EXTRA_INIT 1, &PyType_Type } 0} ,將其代入 PyObject_VAR_HEAD ,得到一個變長對象:
這樣看就很明確了,PyLong_Type的類型就是PyType_Typ,同理可知, Python類型對象的類型就是PyType_Type ,而 PyType_Type對象的類型是它本身
從上述內容中,我們知道了對象和對象類型的定義,那麼根據定義,對象可以有以下兩種分類
Python對象定義有 PyObject 和 PyVarObject ,因此,根據對象大小是否可變的區別,Python對象可以劃分為 可變對象(變長對象) 和 不可變對象(定長對象)
原本的對象a大小並沒有改變,只是s引用的對象改變了。這里的對象a、對象b就是定長對象
可以看到,變數l仍然指向對象a,只是對象a的內容發生了改變,數據量變大了。這里的對象a就是變長對象
由於存在以上特性,所以使用這兩種對象還會帶來一種區別:
聲明 s2 = s ,修改s的值: s = 'new string' ,s2的值不會一起改變,因為只是s指向了一個新的對象,s2指向的舊對象的值並沒有發生改變
聲明 l2 = l ,修改l的值: l.append(6) ,此時l2的值會一起改變,因為l和l2指向的是同一個對象,而該對象的內容被l修改了
此外,對於 字元串 對象,Python還有一套內存復用機制,如果兩個字元串變數值相同,那它們將共用同一個對象:
對於 數值型 對象,Python會默認創建0~2 8 以內的整數對象,也就是 0 ~ 256 之間的數值對象是共用的:
按照Python數據類型,對象可分為以下幾類:
Python創建對象有兩種方式,泛型API和和類型相關的API
這類API通常以 PyObject_xxx 的形式命名,可以應用在任意Python對象上,如:
使用 PyObjecg_New 創建一個數值型對象:
這類API通常只能作用於一種類型的對象上,如:
使用 PyLong_FromLong 創建一個數值型對象:
在我們使用Python聲明變數的時候,並不需要為變數指派類型,在給變數賦值的時候,可以賦值任意類型數據,如:
從Python對象的定義我們已經可以知曉造成這個特點的原因了,Python創建對象時,會分配內存進行初始化,然後Python內部通過 PyObject* 變數來維護這個對象,所以在Python內部各函數直接傳遞的都是一種泛型指針 PyObject* ,這個指針所指向的對象類型是不固定的,只能通過所指對象的 ob_type 屬性動態進行判斷,而Python正是通過 ob_type 實現了多態機制
Python在管理維護對象時,通過引用計數來判斷內存中的對象是否需要被銷毀,Python中所有事物都是對象,所有對象都有引用計數 ob_refcnt 。
當一個對象的引用計數減少到0之後,Python將會釋放該對象所佔用的內存和系統資源。
但這並不意味著最終一定會釋放內存空間,因為頻繁申請釋放內存會大大降低Python的執行效率,因此Python中採用了內存對象池的技術,是的對象釋放的空間會還給內存池,而不是直接釋放,後續需要申請空間時,優先從內存對象池中獲取。
⑵ 有關python中類的聲明和應用。
class human:
def __init__(self, name, sex, weight):
self.name=name
self.sex=sex
self.weight=weight
def detail(self):
print "%s %s %d" %(self.name, self.sex, self.weight)
tom=human("tom", "male", 85)
用的時候就
tom.sex
tom.name之類就行了
函數就
tom.detail()就行了
⑶ python用什麼來定義類對象
Class 關梁團鍵字是燃州用來描述類對象的。橡段橘
⑷ python的模塊和類有什麼區別
python模塊是:
自我包含並且有組織的代碼片段為模塊。
表現形式為:寫的代碼保存為文件。這個文件就是一個模塊。sample.py 其中文件名smaple為模塊名字。
python中的類
類(Class):用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例 。類變數:
類變數在整個實例化的對象中是公用的。類變數定義在類中且在函數體之外。類變數通常不作為實例變數使用。數據成員:類變數或者實
例變數, 用於處理類及其實例對象的相關的數據。方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程
叫方法的覆蓋(override),也稱為方法的重寫。局部變數:定義在方法中的變數,只作用於當前實例的類。實例變數:在類的聲明中,
屬性是用變數來表示的。這種變數就稱為實例變數,是在類聲明的內部但是在類的其他成員方法之外聲明的。繼承:即一個派生類
(derived class)繼承基類(base class)的欄位和方法。繼承也允許把一個派生類的對象作為一個基類對象對待。例如,有這樣一個設
計:一個Dog類型的對象派生自Animal類,這是模擬"是一個(is-a)"關系(例圖,Dog是一個Animal)。實例化:創建一個類的實
例,類的具體對象。方法:類中定義的函數。對象:通過類定義的數據結構實例。對象包括兩個數據成員(類變數和實例變數)和方法。
推薦學習《python教程》。
⑸ python 定義一個類實現以下方法
students={}#uid:name
classStudent(object):
def__init__(self):
pass
defregister(self,uid,name):
students[str(uid)]=name;
deffind_student_by_id(self,uid):
name=None
ifstr(uid)instudents:
name=students[str(uid)]
者吵源returnname
defsorting(self):
lis=[]
碰肢foriinrange(len(students)):
ifstr(i)instudents:
首態lis.append(students[str(i)])
returnlis
classCollege_Student(Student):
def__init__(slef):
pass
defsorting(self):
returnStudent.sorting()[::-1]
⑹ 如何在Python中使用static,class,abstract方法
方法在Python中是如何工作的
方法就是一個函數,它作為一個類屬性而存在,你可以用如下方式來聲明、訪問一個函數:
Python
>>> class Pizza(object):
... def __init__(self, size):
... self.size = size
... def get_size(self):
... return self.size
...
>>> Pizza.get_size
<unbound method Pizza.get_size>
Python在告訴你,屬性_get_size是類Pizza的一個未綁定方法。這是什麼意思呢?很快我們就會知道答案:
Python
>>> Pizza.get_size()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)
我們不能這么調用,因為它還沒有綁定到Pizza類的任何實例上,它需要一個實例作為第一個參數傳遞進去(Python2必須是該類的實例,Python3中可以是任何東西),嘗試一下:
Python
>>> Pizza.get_size(Pizza(42))
42
>>> Pizza.get_size(Pizza(42))
42
太棒了,現在用一個實例作為它的的第一個參數來調用,整個世界都清靜了,如果我說這種調用方式還不是最方便的,你也會這么認為的;沒錯,現在每次調用這個方法的時候我們都不得不引用這個類,如果不知道哪個類是我們的對象,長期看來這種方式是行不通的。
那麼Python為我們做了什麼呢,它綁定了所有來自類_Pizza的方法以及該類的任何一個實例的方法。也就意味著現在屬性get_size是Pizza的一個實例對象的綁定方法,這個方法的第一個參數就是該實例本身。
Python
>>> Pizza(42).get_size
<bound method Pizza.get_size of <__main__.Pizza object at 0x7f3138827910>>
>>> Pizza(42).get_size()
42
和我們預期的一樣,現在不再需要提供任何參數給_get_size,因為它已經是綁定的,它的self參數會自動地設置給Pizza實例,下面代碼是最好的證明:
Python
>>> m = Pizza(42).get_size
>>> m()
42
更有甚者,你都沒必要使用持有Pizza對象的引用了,因為該方法已經綁定到了這個對象,所以這個方法對它自己來說是已經足夠了。
也許,如果你想知道這個綁定的方法是綁定在哪個對象上,下面這種手段就能得知:
Python
>>> m = Pizza(42).get_size
>>> m.__self__
<__main__.Pizza object at 0x7f3138827910>
>>> # You could guess, look at this:
...
>>> m == m.__self__.get_size
True
顯然,該對象仍然有一個引用存在,只要你願意你還是可以把它找回來。
在Python3中,依附在類上的函數不再當作是未綁定的方法,而是把它當作一個簡單地函數,如果有必要它會綁定到一個對象身上去,原則依然和Python2保持一致,但是模塊更簡潔:
Python
>>> class Pizza(object):
... def __init__(self, size):
... self.size = size
... def get_size(self):
... return self.size
...
>>> Pizza.get_size
<function Pizza.get_size at 0x7f307f984dd0>
靜態方法
靜態方法是一類特殊的方法,有時你可能需要寫一個屬於這個類的方法,但是這些代碼完全不會使用到實例對象本身,例如:
Python
class Pizza(object):
@staticmethod
def mix_ingredients(x, y):
return x + y
def cook(self):
return self.mix_ingredients(self.cheese, self.vegetables)
這個例子中,如果把_mix_ingredients作為非靜態方法同樣可以運行,但是它要提供self參數,而這個參數在方法中根本不會被使用到。這里的@staticmethod裝飾器可以給我們帶來一些好處:
Python不再需要為Pizza對象實例初始化一個綁定方法,綁定方法同樣是對象,但是創建他們需要成本,而靜態方法就可以避免這些。
Python
>>> Pizza().cook is Pizza().cook
False
>>> Pizza().mix_ingredients is Pizza.mix_ingredients
True
>>> Pizza().mix_ingredients is Pizza().mix_ingredients
True
可讀性更好的代碼,看到@staticmethod我們就知道這個方法並不需要依賴對象本身的狀態。
可以在子類中被覆蓋,如果是把mix_ingredients作為模塊的頂層函數,那麼繼承自Pizza的子類就沒法改變pizza的mix_ingredients了如果不覆蓋cook的話。
類方法
話雖如此,什麼是類方法呢?類方法不是綁定到對象上,而是綁定在類上的方法。
Python
>>> class Pizza(object):
... radius = 42
... @classmethod
... def get_radius(cls):
... return cls.radius
...
>>>
>>> Pizza.get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza().get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza.get_radius is Pizza().get_radius
True
>>> Pizza.get_radius()
42
無論你用哪種方式訪問這個方法,它總是綁定到了這個類身上,它的第一個參數是這個類本身(記住:類也是對象)。
什麼時候使用這種方法呢?類方法通常在以下兩種場景是非常有用的:
工廠方法:它用於創建類的實例,例如一些預處理。如果使用@staticmethod代替,那我們不得不硬編碼Pizza類名在函數中,這使得任何繼承Pizza的類都不能使用我們這個工廠方法給它自己用。
Python
class Pizza(object):
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def from_fridge(cls, fridge):
return cls(fridge.get_cheese() + fridge.get_vegetables())
調用靜態類:如果你把一個靜態方法拆分成多個靜態方法,除非你使用類方法,否則你還是得硬編碼類名。使用這種方式聲明方法,Pizza類名明永遠都不會在被直接引用,繼承和方法覆蓋都可以完美的工作。
Python
class Pizza(object):
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_area(radius):
return math.pi * (radius ** 2)
@classmethod
def compute_volume(cls, height, radius):
return height * cls.compute_area(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
抽象方法
抽象方法是定義在基類中的一種方法,它沒有提供任何實現,類似於Java中介面(Interface)裡面的方法。
在Python中實現抽象方法最簡單地方式是:
Python
class Pizza(object):
def get_radius(self):
raise NotImplementedError
任何繼承自_Pizza的類必須覆蓋實現方法get_radius,否則會拋出異常。
這種抽象方法的實現有它的弊端,如果你寫一個類繼承Pizza,但是忘記實現get_radius,異常只有在你真正使用的時候才會拋出來。
Python
>>> Pizza()
<__main__.Pizza object at 0x7fb747353d90>
>>> Pizza().get_radius()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
File "<stdin>", line 3, in get_radius
NotImplementedError
還有一種方式可以讓錯誤更早的觸發,使用Python提供的abc模塊,對象被初始化之後就可以拋出異常:
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_radius(self):
"""Method that should do something."""
使用abc後,當你嘗試初始化BasePizza或者任何子類的時候立馬就會得到一個TypeError,而無需等到真正調用get_radius的時候才發現異常。
Python
>>> BasePizza()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius
混合靜態方法、類方法、抽象方法
當你開始構建類和繼承結構時,混合使用這些裝飾器的時候到了,所以這里列出了一些技巧。
記住,聲明一個抽象的方法,不會固定方法的原型,這就意味著雖然你必須實現它,但是我可以用任何參數列表來實現:
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_ingredients(self):
"""Returns the ingredient list."""
class Calzone(BasePizza):
def get_ingredients(self, with_egg=False):
egg = Egg() if with_egg else None
return self.ingredients + egg
這樣是允許的,因為Calzone滿足BasePizza對象所定義的介面需求。同樣我們也可以用一個類方法或靜態方法來實現:
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_ingredients(self):
"""Returns the ingredient list."""
class DietPizza(BasePizza):
@staticmethod
def get_ingredients():
return None
這同樣是正確的,因為它遵循抽象類BasePizza設定的契約。事實上get_ingredients方法並不需要知道返回結果是什麼,結果是實現細節,不是契約條件。
因此,你不能強制抽象方法的實現是一個常規方法、或者是類方法還是靜態方法,也沒什麼可爭論的。從Python3開始(在Python2中不能如你期待的運行,見issue5867),在abstractmethod方法上面使用@staticmethod和@classmethod裝飾器成為可能。
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
ingredient = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.ingredients
別誤會了,如果你認為它會強制子類作為一個類方法來實現get_ingredients那你就錯了,它僅僅表示你實現的get_ingredients在BasePizza中是一個類方法。
可以在抽象方法中做代碼的實現?沒錯,Python與Java介面中的方法相反,你可以在抽象方法編寫實現代碼通過super()來調用它。(譯註:在Java8中,介面也提供的默認方法,允許在介面中寫方法的實現)
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
default_ingredients = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.default_ingredients
class DietPizza(BasePizza):
def get_ingredients(self):
return ['egg'] + super(DietPizza, self).get_ingredients()
這個例子中,你構建的每個pizza都通過繼承BasePizza的方式,你不得不覆蓋get_ingredients方法,但是能夠使用默認機制通過super()來獲取ingredient列表。
⑺ python類的定義與使用是什麼
類Class:用來描述具體相同的屬性和方法的對象的集合。定義了該集合中每個對象所共有的屬性和方法。對象是類的示例。
類定義完成時(正常退出),就創建了一個 類對象。基本上它是對類定義創建的命名空間進行了一個包裝;我們在下一節進一步學習類對象的知識。原始的局部作用域(類定義引入之前生效的那個)得到恢復,類對象在這里綁定到類定義頭部的類名(例子中是 ClassName )。
基本語法
Python的設計目標之一是讓代碼具備高度的可閱讀性。它設計時盡量使用其它語言經常使用的標點符號和英文單字,讓代碼看起來整潔美觀。它不像其他的靜態語言如C、Pascal那樣需要重復書寫聲明語句,也不像它們的語法那樣經常有特殊情況和意外。
以上內容參考:網路-Python
⑻ python 類的定義
Python編程中類定義,代碼如下:
class<類名>:
<語句>
定義類的專有方法:
__init__構造函數,在生成對象時調用
__del__析構函數,釋放對象時使用
__repr__列印,轉換
__setitem__按照索引賦值
__getitem__按照索引獲取值
__len__獲得長度
__cmp__比較運算
__call__函數調用
__add__加運算
__sub__減運算
__mul__乘運算
__div__除運算
__mod__求余運算
__pow__稱方
代碼如下:
#類定義
classpeople:
#定義基本屬性
name=''
age=0
#定義私有屬性,私有屬性在類外部無法直接進行訪問
__weight=0
#定義構造方法
def__init__(self,n,a,w):
self.name=n
self.age=a
self.__weight=w
defspeak(self):
print("%sisspeaking:Iam%dyearsold"%(self.name,self.age))
p=people('tom',10,30)
p.speak()
⑼ pythondef裡面可以用自己定義的類嗎
pythondef裡面可以用自枯老己定義的類。pythondef裡面用自己定義的類叫做自定義類。Python中定槐敗脊義一個類很簡單,只需要使用關鍵詞class去聲明即可。python之中想要去使用一個類,那就必須鉛滲去實例化這個類,使用這個類的對象去使用它。
⑽ python如何使用一個自己定義好的模塊中的類
Chain.py是模塊(Mole),
在代碼里定義的Class Chain是在模塊物罩里定義的類
一種方法是from Chain import Chain
還有一種方法是洞凳用 a = Chain.Chain()
相當於從模納螞旅塊里索引出這個類
兩種方法都可以。