بيثون tabstop علم ليون () والحشو وظائف
سؤال
وليون بايثون () والحشو وظائف مثل string.ljust () لا tabstop على علم، أي أنها علاج '\ ر' مثل أي حرف آخر وحيد العرض، وليس ليون الجولة تصل إلى أقرب مضاعف من tabstop . مثال:
len('Bear\tnecessities\t')
وهو 17 بدلا من 24 (أي 4+ (8-4) +11+ (8-3))
ويقول أريد أيضا pad_with_tabs(s)
دالة على ان هذه
pad_with_tabs('Bear', 15) = 'Bear\t\t'
وتبحث عن تطبيقات بسيطة من هذه - الاكتناز وسهولة القراءة أولا، وكفاءة الثانية. هذا هو السؤال الأساسي ولكن غضب. gnibbler - يمكن أن تظهر لك حل Pythonic بحتة، حتى لو كان يقول 20x وأقل كفاءة
هل أنت متأكد أنك يمكن تحويل ذهابا وإيابا باستخدام str.expandtabs (TABWIDTH)، ولكن هذا في عالي الكعب.
استيراد الرياضيات للحصول على TABWIDTH * int( math.ceil(len(s)*1.0/TABWIDTH) )
يبدو أيضا مثل مبالغة واسعة النطاق.
وأنا لا يمكن أن إدارة أي شيء أكثر أناقة من ما يلي:
TABWIDTH = 8
def pad_with_tabs(s,maxlen):
s_len = len(s)
while s_len < maxlen:
s += '\t'
s_len += TABWIDTH - (s_len % TABWIDTH)
return s
ومنذ سلاسل بيثون هي ثابتة وإلا إذا كنا نريد أن القرد التصحيح وظيفتنا في وحدة سلسلة لإضافته كوسيلة من وسائل، ويجب علينا أيضا تعيين إلى نتيجة الدالة:
s = pad_with_tabs(s, ...)
وعلى وجه الخصوص لم أستطع الحصول على النهج نظيفة باستخدام قائمة الفهم أو string.join (...)
''.join([s, '\t' * ntabs])
ودون خاص غلاف الحالات التي يكون فيها ليون (ق) هو <مضاعف صحيح من TABWIDTH، أو ليون (ق) => MAXLEN بالفعل.
ويمكن لأي شخص تظهر ليون أفضل () وpad_with_tabs () وظائف؟
المحلول
TABWIDTH=8
def my_len(s):
return len(s.expandtabs(TABWIDTH))
def pad_with_tabs(s,maxlen):
return s+"\t"*((maxlen-len(s)-1)/TABWIDTH+1)
لماذا يمكنني استخدام expandtabs()
منتديات
حسنا انها سريعة
$ python -m timeit '"Bear\tnecessities\t".expandtabs()'
1000000 loops, best of 3: 0.602 usec per loop
$ python -m timeit 'for c in "Bear\tnecessities\t":pass'
100000 loops, best of 3: 2.32 usec per loop
$ python -m timeit '[c for c in "Bear\tnecessities\t"]'
100000 loops, best of 3: 4.17 usec per loop
$ python -m timeit 'map(None,"Bear\tnecessities\t")'
100000 loops, best of 3: 2.25 usec per loop
وأي شيء بالتكرار عبر سلسلة الخاص بك سيكون أبطأ، لمجرد التكرار هو ~ 4 مرات أبطأ من expandtabs
حتى عندما كنت لا تفعل شيئا في الحلقة.
$ python -m timeit '"Bear\tnecessities\t".split("\t")'
1000000 loops, best of 3: 0.868 usec per loop
وحتى تقسيم فقط على علامات التبويب وقتا أطول. كنت لا تزال بحاجة إلى كرر أكثر من الانقسام وسادة كل عنصر إلى tabstop
نصائح أخرى
وأعتقد gnibbler هو الأفضل بالنسبة لمعظم الحالات prectical. ولكن على أي حال، وهنا هو ساذج (دون محاسبة CR، LF الخ) حل لحساب طول سلسلة دون خلق توسيع نسخة:
def tab_aware_len(s, tabstop=8):
pos = -1
extra_length = 0
while True:
pos = s.find('\t', pos+1)
if pos<0:
return len(s) + extra_length
extra_length += tabstop - (pos+extra_length) % tabstop - 1
وربما يمكن أن تكون مفيدة لبعض سلاسل ضخمة أو الذاكرة حتى الملفات المعينة. وهنا هي وظيفة الحشو الأمثل قليلا:
def pad_with_tabs(s, max_len, tabstop=8):
length = tab_aware_len(s, tabstop)
if length<max_len:
s += '\t' * ((max_len-1)//tabstop + 1 - length//tabstop)
return s
وTABWIDTH * int( math.ceil(len(s)*1.0/TABWIDTH) )
هو في الواقع ضخمة على القتل. يمكنك الحصول على نفس النتيجة أكثر من ذلك بكثير ببساطة. لi
إيجابية وn
، الاستخدام:
def round_up_positive_int(i, n):
return ((i + n - 1) // n) * n
ويعمل هذا الإجراء فقط في أي لغة لقد استعملت من أي وقت مضى، بعد الترجمة المناسبة.
وبعد ذلك يمكنك القيام به next_pos = round_up_positive_int(len(s), TABWIDTH)
لزيادة طفيفة في الأناقة من التعليمات البرمجية الخاصة بك، بدلا من
while(s_len < maxlen):
استخدم هذا:
while s_len < maxlen: