2013-10-22 16 views
2

所以我對學習裝飾器很陌生,我經歷了無數的教程,雖然我理解並且大多可以遵循所有的例子,但我認爲最好的學習方法是自己實現一個裝飾器。所以我將在下面使用這個例子。我意識到一個裝飾器根本就沒有必要這樣做,但爲了學習,我想添加一個裝飾器來過濾像狗的名字和品種這樣的字符串,並將它們變成小寫字母。任何想法或指針在正確的方向將不勝感激。在Python中添加一個將字符串轉換爲小寫的裝飾器

class Dogs: 
    totalDogs = 0 
    dogList=[] 

    def __init__(self, breed, color, age): 
     self.breed=breed 
     self.color=color 
     self.age=age 
     Dogs.dogList.append(self.breed) 
     Dogs.totalDogs += 1 

    def displayDogs(self): 
     print "breed: ", self.breed 
     print "color: ",self.color 
     print "age: ",self.age 
     print "list of breeds:", Dogs.dogList 
     print "total dogs: ", Dogs.totalDogs 

def somedecorator(*args): 
    #now what 

terrier=Dogs("TeRrIer", "white", 5) 
terrier.displayDogs() 
retriever=Dogs("goldenRETRIEVER", "brown", 10) 
retriever.displayDogs() 
+0

到底是什麼,你正在尋找的輸出?是不是像string.lower()函數那樣小寫,但是你想用ascii值來實現它? – RMcG

+0

恩,我不確定你剛纔問的是哪一件。爲了澄清,沒有一個對我很重要,我只是試圖實現某種裝飾器來了解更多關於裝飾器的知識。 – stephan

+0

如果你想要去比特級這篇文章應該幫助http://stackoverflow.com/questions/3569874/how-do-uppercase-and-lowercase-letters-differ-by-only-one-bit/3570520# 3570520 – RMcG

回答

1

裝飾器實際上就是一個函數,函數的參數和返回另一個功能。

def lower_output(func): 
    def wrapper(*args, **kwargs): 
     return func(*args, **kwargs).lower() 
    return wrapper 


class Dogs(object): 
    totalDogs = 0 
    dogList=[] 

    def __init__(self, breed, color, age): 
     self.breed=breed 
     self.color=color 
     self.age=age 
     Dogs.dogList.append(self.breed) 
     Dogs.totalDogs += 1 

    @lower_output 
    def get_breed(self): 
     return self.breed 




>>> terrier=Dogs("TeRrIer", "white", 5) 
>>> terrier.get_breed() 
terrier 
+1

感謝您的幫助,雖然我得到一個錯誤,說第12行lower_output沒有定義 – stephan

+1

嘗試在模塊中進一步定義它,我已經編輯我的例子給你。 – aychedee

2

那麼,爲了簡化它,首先我們來處理函數。比方說,你有一個打印一些關於它的參數的函數:

def print_info(breed, name): 
    print "The doggie %s's breed is %s." % (name, breed) 

這樣:

>>> print_info("Labrador", "Spike") 
The doggie Spike's breed is Labrador. 
>>> print_info("Pit Bull", "Spot") 
The doggie Spot's breed is Pit Bull. 

現在你想要的功能,而不是總是小寫的品種。因此,在一個健全的方式你只是這樣做:

def manually_lowered_print_info(breed, name): 
    print "The doggie %s's breed is %s." % (name, breed.lower()) 

輸出是:

>>> manually_lowered_print_info("Labrador", "Spike") 
The doggie Spike's breed is labrador. 

但是,假設由於某種原因,你經常不得不爲小寫的函數的第一個字符串參數,你寫了這麼你想把它作爲裝飾者來抽象出來。我們希望它看起來像這一點,並具有相同的輸出:

@lower_first_arg 
def dec_lowered_print_info(breed, name): 
    print "The doggie %s's breed is %s." % (name, breed) 

這只是語法糖這樣的:

def tmp_func(breed, name): 
    print "The doggie %s's breed is %s." % (name, breed) 
dec_lowered_print_info = lower_first_arg(tmp_func) 

因此,我們要lower_first_arg回報轉化print_info功能。我們首先爲print_info函數定製一個函數。

def lower_first_arg(print_info_func_arg): 
    def inner_print_info(breed, name): 
     return print_info_func_arg(breed.lower(), name) 
    return inner_print_info 

它工作嗎?讓我們看看:

>>> transformed_print_info = lower_first_arg(print_info) 
>>> print_info("Pit Bull", "Spot") 
The doggie Spot's breed is Pit Bull. 
>>> transformed_print_info("Pit Bull", "Spot") 
The doggie Spot's breed is pit bull. 

太棒了!請注意,我們將print_info作爲參數傳遞給lower_first_arg函數,它被本地變量print_info_func_arg引用。

如果我們使用修飾語法它的工作原理相同:

@lower_first_arg 
def dec_lowered_print_info(breed, name): 
    print "The doggie %s's breed is %s." % (name, breed) 

突出:

>>> dec_lowered_print_info("Pit Bull", "Spot") 
The doggie Spot's breed is pit bull. 

酷,所以就是這樣,真的。現在,爲了裝飾更通用,讓我們先概括名稱:

def generic_lower_first_arg(f): 
    def wrapped(arg1, arg2): 
     return f(arg1.lower(), arg2) 
    return wrapped 

現在這裏的問題是這個裝飾只適用於2個ARGS功能。理想情況下,我們希望它能夠處理1個或更多的任何函數,例如:

@generic_lower_first_arg 
def failed_whatnow(first, last, middle): 
    print "%s %s %s" % (first, middle, last) 

現在,該代碼將運行,但我們得到一個錯誤,如果我們試圖把它叫做:

>>> failed_whatnow("Bob", "Jones", "The Killer") 

Traceback (most recent call last): 
    File "<pyshell#26>", line 1, in <module> 
    failed_whatnow("Bob", "Jones", "The Killer") 
TypeError: wrapped() takes exactly 2 arguments (3 given) 

這是怎麼回事?那麼,裝飾器拿了failed_whatnow並返回了它定義的函數wrapped,但wrapped函數只有兩個參數!這裏的解決方法是使用可變參數語法。傳遞可能賦予包裝函數的關鍵字參數通常也是一個好主意。

def proper_lower_first_arg(f): 
    def wrapped(arg1, *args, **kwargs): 
     return f(arg1.lower(), *args, **kwargs) 
    return wrapped 

而現在它適用於各種功能:

@proper_lower_first_arg 
def proper_whatnow(first, last, middle): 
    print "%s %s %s" % (first, middle, last) 

@proper_lower_first_arg 
def multiplyit(mm, n=3): 
    return mm * n 

證明:

>>> proper_whatnow("Bob", "Jones", "The Killer") 
bob The Killer Jones 
>>> multiplyit("HaHa.Fool!") 
'haha.fool!haha.fool!haha.fool!' 
>>> multiplyit("HaHa.Fool!", n=5) 
'haha.fool!haha.fool!haha.fool!haha.fool!haha.fool!' 
0

修飾器通常用於修改函數/方法的輸入參數或返回值。

方法Dogs.displayDogs不會返回任何數據(None除外),所以它沒有任何意義,說你想使字符串小寫。哪些字符串?您只需打印值。所以,你會怎麼做:

class Dogs: 
    totalDogs = 0 
    dogList=[] 

    def __init__(self, breed, color, age): 
     self.breed=breed 
     self.color=color 
     self.age=age 
     Dogs.dogList.append(self.breed) 
     Dogs.totalDogs += 1 

    def displayDogs(self): 
     print "breed: ", self.breed.lower() 
     print "color: ",self.color.lower() 
     ... 

否則,你應該重構代碼:

def make_lower(func): 
    def wrapper(*args, **kwargs): 
     result = func(*args, **kwargs) 
     result = [value.lower() for value in result] 
     return result 
    return wrapper 

class Dogs: 
    totalDogs = 0 
    dogList=[] 

    def __init__(self, breed, color, age): 
     self.breed=breed 
     self.color=color 
     self.age=age 
     Dogs.dogList.append(self.breed) 
     Dogs.totalDogs += 1 


    @make_lower 
    def getDogs(self): 
     return [ 
      "breed: %s" % self.breed, 
      "color: %s" % self.color.lower(), 
      ... 
     ] 

的你做

terrier = Dogs("TeRrIer", "white", 5) 
print terrier.getDogs() 
相關問題