定製類

strrepr

  • str()返回用戶看到的字符串
  • repr()返回程序開發者看到的字符串,也就是說,repr()是爲調試服務的
class Student(object):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return "Student object name:{}".format(self.name)

    __repr__ = __str__

iter

若是一個類想被用於for ... in循環,相似list或tuple那樣,就必須實現一個__iter__()方法,該方法返回一個迭代對象,而後,Python的for循環就會不斷調用該迭代對象的next()方法拿到循環的下一個值,直到遇到StopIteration錯誤時退出循環,咱們以斐波那契數列爲例,寫一個Fib類,能夠做用於for循環:django

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1  # 初始化2個計數器

    def __iter__(self):
        return self  # 實例自己就是迭代器,返回self

    def next(self):
        self.a, self.b = self.b, self.a + self.b  # 計算下一個值
        if self.a > 100000:  # 退出循環條件
            raise StopIteration()
        return self.a  # 返回下一個值


for n in Fib():
    print n

getitem

Fib實例雖然能做用於for循環,看起來和list有點像,可是,把它當成list來使用仍是不行,好比,取第5個元素,要表現得像list那樣按照下標取出元素,須要實現__getitem__()方法:函數

class Fab(object):
    def __getitem__(self, item):
        a, b = 1, 1
        for x in xrange(item):
            a, b = b, a + b
        return a



f = Fab()
print f[1]
print f[2]

getattr

正常狀況下,當咱們調用類的方法或屬性時,若是不存在,就會報錯。StudentTest類.調用name屬性,沒問題,可是,調用不存在的arg屬性,就有問題了,在getattr裏面能夠作判斷而且返回一個對象:工具

代碼實現:測試

class StudentTest(object):
    def __init__(self):
        self.name = "Hero"

    def __getattr__(self, item):
        if item == 'arg':
            return 27
        else:
            raise ValueError("The key is not found")

st = StudentTest()
print st.name
print st.arg
print st.sexy

實際用例: 將一個字典設置成類屬性訪問調試

經常使用方法:code

class Eleme(object):
    def __init__(self):
        self._dict = {"method": "get"}
        self._list = ["name", "sexy"]
        for key,val in self._dict.items():
            setattr(self, key,val)

    



e = Eleme()

print e.method

# result : get

更好的方法:orm

# -*- coding: utf-8 -*-

class Eleme(object):
    def __init__(self):
        self._dict = {"method": "get"}
        self._list = ["name", "sexy"]

    def __getattr__(self, item):
        return self._dict[item]



e = Eleme()

print e.method

# result : get

call

一個對象實例能夠有本身的屬性和方法,當咱們調用實例方法時,咱們用instance.method()來調用。能不能直接在實例自己上調用呢?相似instance()?在Python中,答案是確定的。 任何類,只須要定義一個__call__()方法,就能夠直接對實例進行調用。請看示例:對象

class CallTest(object):
    def __init__(self, name):
        self.name = name

    def __call__(self, arg = None):
        return "My name is {}. {} old".format(self.name,arg)



c = CallTest("hero")
print c(12)

My name is hero. 12 old

#仿django orm繼承

# -*- coding: utf-8 -*-

class User(object):
    class objects():
        @classmethod
        def create(cls, **kwargs):
            key, val = kwargs.items()[0]
            return "Create successful.key is {key} values is {val}".format(
                key=key, val=val)


print User.objects.create(name="Hero")

# 輸出結果: Create successful.key is name values is Hero

type() 使用元類

動態語言和靜態語言最大的不一樣,就是函數和類的定義,不是編譯時定義的,而是運行時動態建立的。 比方說咱們要定義一個Hello的class,就寫一個hello.py模塊:utf-8

class Hello(object):
    def hello(self, name='world'):
        print('Hello, %s.' % name)

當Python解釋器載入hello模塊時,就會依次執行該模塊的全部語句,執行結果就是動態建立出一個Hello的class對象,測試以下:

>>> from hello import Hello
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class 'hello.Hello'>

type()函數能夠查看一個類型或變量的類型,Hello是一個class,它的類型就是type,而h是一個實例,它的類型就是class Hello。

咱們說class的定義是運行時動態建立的,而建立class的方法就是使用type()函數。

type()函數既能夠返回一個對象的類型,又能夠建立出新的類型,好比,咱們能夠經過type()函數建立出Hello類,而無需經過class Hello(object)...的定義:

>>> def fn(self, name='world'): # 先定義函數
...     print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 建立Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>

要建立一個class對象,type()函數依次傳入3個參數:

一、class的名稱;

二、繼承的父類集合,注意Python支持多重繼承,若是隻有一個父類,別忘了tuple的單元素寫法;

三、class的方法名稱與函數綁定,這裏咱們把函數fn綁定到方法名hello上。

經過type()函數建立的類和直接寫class是徹底同樣的,由於Python解釋器遇到class定義時,僅僅是掃描一下class定義的語法,而後調用type()函數建立出class。

正常狀況下,咱們都用class Xxx...來定義類,可是,type()函數也容許咱們動態建立出類來,也就是說,動態語言自己支持運行期動態建立類,這和靜態語言有很是大的不一樣,要在靜態語言運行期建立類,必須構造源代碼字符串再調用編譯器,或者藉助一些工具生成字節碼實現,本質上都是動態編譯,會很是複雜。

相關文章
相關標籤/搜索