簡體   English   中英

有沒有一種更有效的方法可以根據條件初始化變量?

[英]Is there a more efficient one liner to initialize a variable based on a condition?

可以通過一個內襯初始化atype變量嗎?

def detect(dt,result):
    """ prints the type of date """
    atype = 'unknown'
    if 'greg' in result:
        atype = 'Gregorian'
    elif 'eth' in result:
        atype = 'Ethiopian'

    print '%s is in %s format.' % (dt,atype)

您可以使用一對條件表達式-不需要括號。 就像Python知道應該從左到右合理地完成1 + 2 + 3 ,因此條件表達式可以一個接一個地寫在另一個子句中,而不必擔心解釋器會感到困惑。 換行和縮進對於提高可讀性很重要,因此,我通常這樣做:

atype = ('Gregorian' if 'greg' in result
         else 'Ethiopian' if 'eth' in result
         else 'unknown')

壓痕的這種形式不僅是大多數編輯器將在任何情況下,如果按之前的每個“輸入”產生一個else ,但它使得視覺感很大,我當我回來以后讀我自己,或者是有人否則就是代碼-畢竟,這是我們使用Python的重要原因,對吧? :)

編輯:當然,我意識到這只是單行代碼,因為Python將連續的行視為單行代碼。 所以我想我的答案是,對於我來說,您的程序看起來像Python的一條物理線有點密集,但是如果編寫為Python的一條邏輯線,您的程序將非常不錯!

編輯:另一個注意事項:當然,我認識到我的代碼片段違反了PEP-8,PEP-8表示要終止與運算符的連續行-因此PEP-8將讓我將else詞移到上一行的末尾。 我只能說這是我不同意的PEP-8規則之一,我經常破壞它,因此我產生了更具可讀性的代碼。 我認為在這一點上,我與PEP-8的不同之處在於具有數學排版背景,並且,正如Donald Knuth在TeXBook中強調的那樣,“顯示的公式總是二進制運算和關系之前中斷”(第195頁)。

不知道這是否有意義和可讀...

atype = 'Gregorian' if 'greg' in result else ('Ethiopian' if 'eth' in result else 'unknown')

我個人在一個論壇上提出

def detect(dt,result):
    """ prints the type of date """
    style = 'Gregorian' if 'greg' in result else\
            'Ethiopian' if 'eth'  in result else\
            'unknown'
    print '%s is in %s format.' % (dt,style)

在我的代碼的秘密中,沒有人會來看我是否尊重Python的Zen,我實際上會這樣做:

def detect(dt,result):
    """ prints the type of date """
    print dt + ' is in %s format.'\
          % \
          'Gregorian' if 'greg' in result else\
          'Ethiopian' if 'eth'  in result else\
          'unknown'

我測量了執行時間:第二次執行的時間是第一次執行時間的89%

編輯1

最后,我進行的測試並不令我滿意,因為將完成分配的程序(樣式=等)與沒有等效分配的程序進行比較是不公平的。

因此,我再次使用修改后的代碼進行了測試。為強調代碼之間差異的影響,我添加了一些條件行。

我分別運行以下程序(以避免在不必重新創建的情況下重新分配對象的可能的持久性;我不確切知道Python的內存和對象模型中發生了什么,以及是否可能實際上發生了;但是在衡量執行時間時,有時會發現奇怪的現象。因此,我沒有風險,我將代碼分開)

第一個程序

from time import clock

A=[]

for repeat in xrange(5000):
    def detect(dt,result):
        if 'greg' in result:
            h = '%s is in %s format.' % (dt,'Gregorian')
        elif 'eth' in result:
            h = '%s is in %s format.' % (dt,'Ethiopian')
        elif 'ame' in result:
            h = '%s is in %s format.' % (dt,'American')
        elif 'rus' in result:
            h = '%s is in %s format.' % (dt,'Russian')
        elif 'egyp' in result:
            h = '%s is in %s format.' % (dt,'Egyptian')
        else:
            h = '%s is in unknown format.' % dt

    te = clock()
    for i in xrange(10000):
        detect('zozo',' he is egyptolog')
    A.append(clock() - te)

print min(A)

第二程序

from time import clock

B=[]

for repeat in xrange(5000):


def detect(dt,result):
    x  = '%s is in %s format.' % (dt,'Gregorian' if 'greg' in result else\
                                  'Ethiopian' if 'eth'  in result else\
                                  'American' if 'ame'  in result else\
                                  'Russian' if 'rus'  in result else\
                                  'Egyptian' if 'egyp'  in result else\
                                  'unknown')

te = clock()
for i in xrange(10000):
    detect('zozo',' he is egyptolog')
B.append(clock() - te)

print min(B)

第三程序

from time import clock

C = []

for repeat in xrange(1000):
    def detect(dt,result):
        y = dt + ' is in %s format.'\
            % \
            'Gregorian' if 'greg' in result else\
            'Ethiopian' if 'eth'  in result else\
            'American' if 'ame'  in result else\
            'Russian' if 'rus'  in result else\
            'Egyptian' if 'egyp'  in result else\
            'unknown'

    te = clock()
    for i in xrange(10000):
        detect('zozo',' he is egyptolog')
    C.append(clock() - te)

print min(C)

我獲得了

0.0198832秒

0,019962秒

0,012664秒

結論:

  • 使用if-elif-else條件或if-else-else-else連續條件編寫代碼的方式之間沒有區別。

    然后,即使第二種方式並不比delnan認為的那么殘酷,但它的可立即理解性卻稍差一些,因此我最終發現,第一種寫作方式由於其完美的可讀性而比第二種寫作方式更好,而且絲毫沒有損失性能。

    如果無法使用if-elif-else,例如用於列表理解或編寫lambda函數,則在某些情況下使用if-else-else很有趣,這是唯一的解決方案。

  • 這次,我的代碼運行時間是其他兩次執行​​時間的64%。 要檢查的條件越多,我的代碼就越快

    如果有人擔心性能,則可以使用此解決方案。 如果沒有,對我來說,一系列if-elif-else條件似乎是最佳選擇。

編輯2

@吃,

假設一百萬個元素的列表,像這個

li = [('greg','Gregorian'),('eth','Ethiopian')]

已使用cPickle以序列化格式記錄。 然后代碼將是:

import cPickle  

with open('trynewline.txt','r') as f:
    li = cPickle.load(f)

def detect(dt,result):
    for a,b in li:
        if a in result:
            return '%s is in %s format.' % (dt,b)
        else:
            return '%s is in unknown format.' % dt

要么

import cPickle  

with open('trynewline.txt','r') as f:
    li = cPickle.load(f)

def detect(dt,result):
    ha = [ b for a,b in li if a in result]
    y = dt + ' is in %s format.'\
        % (ha[0] if ha else 'unknown')

就這樣。 無論如何, li中包含的數據必須來自某個地方。 它可以自動生產; 或手動生產。 如果它是手工制作的,並且沒有人在我之前創建,那么我將不得不自己寫一百萬個條件。 如果是您必須編寫代碼,那么您也將這樣做。 我看不出如何用字典避免這種情況。

是的,Python變量的范圍與其他編程語言有點不同。 所以,

if 'greg' in result:
    atype = 'Gregorian' 

print(atype)

會做的很好。

if 'greg' in result: atype = 'Gregorian'
print(atype)

可以使用,除非它是Python Shell(您必須執行整個腳本)

但是無論如何,進行非常長的,與條件相關的變量初始化是一個不好的做法。

其實很奇怪,但是..這只是一種不同的方式..我認為擴展起來更容易,但是我想還有更好的方法;)

import operator as op
import functools as fc

atype = {'greg':'Gregorian', 'eth':'Ethiopian'}.get(filter(fc.partial(op.contains, ('greg', 'eth')), res)[0], 'unknown')

盡管有單獨的行來設置字典,但這里有一個單行(為了便於閱讀,請展開兩行):

typemap = {'greg': 'Gregorian', 'eth': 'Ethiopian'}

atype = ([typemap[frag] for frag in typemap if frag in result][0]
         if any(frag in result for frag in typemap) else 'unknown')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM