ใครที่นี่มีโค้ดที่เป็นประโยชน์ซึ่งใช้ฟังก์ชันลด () ใน python หรือไม่? มีรหัสอื่นนอกเหนือจาก + และ * ปกติที่เราเห็นในตัวอย่างหรือไม่?
อ้างถึงFate of reduction () ใน Python 3000โดย GvR
ใครที่นี่มีโค้ดที่เป็นประโยชน์ซึ่งใช้ฟังก์ชันลด () ใน python หรือไม่? มีรหัสอื่นนอกเหนือจาก + และ * ปกติที่เราเห็นในตัวอย่างหรือไม่?
อ้างถึงFate of reduction () ใน Python 3000โดย GvR
คำตอบ:
การใช้งานอื่น ๆ ที่ฉันพบนอกเหนือจาก + และ * คือกับและหรือ แต่ตอนนี้เรามีany
และall
แทนที่กรณีเหล่านั้น
foldl
และfoldr
เกิดขึ้นในโครงการมากมาย ...
นี่คือการใช้งานที่น่ารัก:
แบนรายการ
ประตู: เปิดเข้าไป[[1, 2, 3], [4, 5], [6, 7, 8]]
[1, 2, 3, 4, 5, 6, 7, 8]
reduce(list.__add__, [[1, 2, 3], [4, 5], [6, 7, 8]], [])
รายการหลักเป็นตัวเลข
ประตู: เปิดเข้าไป[1, 2, 3, 4, 5, 6, 7, 8]
12345678
วิธีที่น่าเกลียดและช้า:
int("".join(map(str, [1,2,3,4,5,6,7,8])))
พริตตี้reduce
ทาง:
reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0)
timeit.repeat('int("".join(map(str, digit_list)))', setup = 'digit_list = list(d%10 for d in xrange(1,1000))', number=1000)
ใช้เวลา ~ 0.09 วินาทีและtimeit.repeat('reduce(lambda a,d: 10*a+d, digit_list)', setup = 'digit_list = list(d%10 for d in xrange(1,1000))', number=1000)
ใช้เวลา 0.36 วินาที (ช้ากว่าประมาณ 4 เท่า) โดยทั่วไปการคูณด้วย 10 จะมีราคาแพงเมื่อรายการมีขนาดใหญ่ในขณะที่ int ถึง str และการเรียงต่อกันยังคงถูก
timeit.repeat('convert_digit_list_to_int(digit_list)', setup = 'digit_list = [d%10 for d in xrange(1,10)]\ndef convert_digit_list_to_int(digits):\n i = 0\n for d in digits:\n i = 10*i + d\n return i', number=100000)
ก็ใช้เวลา 0.06 วินาทีtimeit.repeat('reduce(lambda a,d: 10*a+d, digit_list)', setup = 'digit_list = list(d%10 for d in xrange(1,10))', number=100000)
ใช้เวลา 0.12 วินาทีและการแปลงหลักเป็นวิธี str จะใช้เวลา 0.16 วินาที
reduce()
สามารถใช้เพื่อค้นหาตัวคูณน้อยที่สุดสำหรับตัวเลข 3 ตัวขึ้นไป :
#!/usr/bin/env python
from fractions import gcd
from functools import reduce
def lcm(*args):
return reduce(lambda a,b: a * b // gcd(a, b), args)
ตัวอย่าง:
>>> lcm(100, 23, 98)
112700
>>> lcm(*range(1, 20))
232792560
lcm
ในบรรทัดที่สอง?
reduce()
สามารถใช้เพื่อแก้ไขชื่อที่eval()
เป็นจุด (ซึ่งไม่ปลอดภัยที่จะใช้):
>>> import __main__
>>> reduce(getattr, "os.path.abspath".split('.'), __main__)
<function abspath at 0x009AB530>
ค้นหาจุดตัดของ N รายการที่กำหนด:
input_list = [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]
result = reduce(set.intersection, map(set, input_list))
ผลตอบแทน:
result = set([3, 4, 5])
ฉันคิดว่าการลดเป็นคำสั่งโง่ ๆ ดังนั้น:
reduce(lambda hold,next:hold+chr(((ord(next.upper())-65)+13)%26+65),'znlorabggbbhfrshy','')
การใช้reduce
สิ่งที่ฉันพบในโค้ดของฉันเกี่ยวข้องกับสถานการณ์ที่ฉันมีโครงสร้างคลาสสำหรับนิพจน์ตรรกะและฉันจำเป็นต้องแปลงรายการของอ็อบเจ็กต์นิพจน์เหล่านี้เป็นการรวมกันของนิพจน์ ฉันได้มีฟังก์ชั่นในการสร้างร่วมให้ทั้งสองสำนวนดังนั้นฉันเขียนmake_and
reduce(make_and,l)
(ฉันรู้ว่ารายการไม่ว่างเปล่ามิฉะนั้นจะเป็นเช่นreduce(make_and,l,make_true)
นั้น)
นี่คือเหตุผลที่ (บางคน) โปรแกรมเมอร์ที่ใช้งานได้ชอบreduce
(หรือฟังก์ชันพับตามที่มักเรียกว่าฟังก์ชันดังกล่าว) มีฟังก์ชั่นไบนารีมักจำนวนมากอยู่แล้วเหมือน+
, *
, min
, max
, เรียงต่อกันและในกรณีของฉันและmake_and
make_or
การมีส่วนreduce
ช่วยในการยกการดำเนินการเหล่านี้ไปยังรายการ (หรือต้นไม้หรืออะไรก็ได้ที่คุณมีสำหรับฟังก์ชันพับโดยทั่วไป)
แน่นอนว่าหากsum
มักใช้อินสแตนซ์บางอย่าง (เช่น) คุณก็ไม่ต้องการเขียนreduce
ต่อ อย่างไรก็ตามแทนที่จะกำหนดsum
ด้วย for-loop คุณสามารถกำหนดได้อย่างง่ายดายด้วยreduce
.
ความสามารถในการอ่านตามที่ผู้อื่นกล่าวถึงเป็นปัญหาอย่างแท้จริง อย่างไรก็ตามคุณสามารถโต้แย้งได้ว่าเหตุผลเดียวที่ทำให้ผู้คนเห็นว่าreduce
"ชัดเจน" น้อยลงเป็นเพราะมันไม่ใช่ฟังก์ชั่นที่หลายคนรู้จักและ / หรือใช้
and
ตัวดำเนินการ: L and reduce(make_and, L)
หากการส่งคืนรายการว่างนั้นเหมาะสมในกรณีนี้
องค์ประกอบของฟังก์ชัน : หากคุณมีรายการฟังก์ชันที่ต้องการใช้ต่อเนื่องกันเช่น:
color = lambda x: x.replace('brown', 'blue')
speed = lambda x: x.replace('quick', 'slow')
work = lambda x: x.replace('lazy', 'industrious')
fs = [str.lower, color, speed, work, str.title]
จากนั้นคุณสามารถใช้ทั้งหมดติดต่อกันด้วย:
>>> call = lambda s, func: func(s)
>>> s = "The Quick Brown Fox Jumps Over the Lazy Dog"
>>> reduce(call, fs, s)
'The Slow Blue Fox Jumps Over The Industrious Dog'
ในกรณีนี้การเชื่อมโยงวิธีการอาจอ่านได้ง่ายขึ้น แต่บางครั้งก็เป็นไปไม่ได้และองค์ประกอบประเภทนี้อาจอ่านและบำรุงรักษาได้มากกว่าf1(f2(f3(f4(x))))
ไวยากรณ์ประเภทหนึ่ง
คุณสามารถแทนที่value = json_obj['a']['b']['c']['d']['e']
ด้วย:
value = reduce(dict.__getitem__, 'abcde', json_obj)
หากคุณมีเส้นทางa/b/c/..
เป็นรายการอยู่แล้ว ยกตัวอย่างเช่นการเปลี่ยนค่าใน Dict ของ dicts ซ้อนกันโดยใช้รายการในรายการ
@ แบลร์คอนราด: คุณสามารถใช้ glob / ลดโดยใช้ sum ได้เช่นกัน:
files = sum([glob.glob(f) for f in args], [])
นี่เป็นรายละเอียดน้อยกว่าตัวอย่างทั้งสองของคุณเป็น Pythonic ที่สมบูรณ์แบบและยังคงเป็นโค้ดเพียงบรรทัดเดียว
ดังนั้นเพื่อตอบคำถามเดิมโดยส่วนตัวฉันพยายามหลีกเลี่ยงการใช้การลดเพราะมันไม่จำเป็นจริงๆและฉันพบว่ามันชัดเจนน้อยกว่าวิธีอื่น ๆ อย่างไรก็ตามบางคนเคยชินกับการลดลงและชอบที่จะแสดงรายการความเข้าใจ (โดยเฉพาะโปรแกรมเมอร์ของ Haskell) แต่ถ้าคุณยังไม่ได้คิดเกี่ยวกับปัญหาในแง่ของการลดคุณอาจไม่จำเป็นต้องกังวลเกี่ยวกับการใช้งาน
sum
และreduce
นำไปสู่พฤติกรรมกำลังสอง สามารถทำได้ในเวลาเชิงเส้น: files = chain.from_iterable(imap(iglob, args))
. แม้ว่าอาจไม่สำคัญในกรณีนี้เนื่องจากต้องใช้เวลาในการเข้าถึงดิสก์ glob ()
reduce
สามารถใช้เพื่อสนับสนุนการค้นหาแอตทริบิวต์ที่ถูกล่ามโซ่:
reduce(getattr, ('request', 'user', 'email'), self)
แน่นอนว่านี่เทียบเท่ากับ
self.request.user.email
แต่จะมีประโยชน์เมื่อรหัสของคุณต้องยอมรับรายการแอตทริบิวต์โดยพลการ
(คุณลักษณะที่ถูกล่ามโซ่ของความยาวโดยพลการเป็นเรื่องปกติเมื่อจัดการกับโมเดล Django)
reduce
มีประโยชน์เมื่อคุณต้องการค้นหาการรวมกันหรือจุดตัดของลำดับของset
วัตถุที่เหมือนกัน
>>> reduce(operator.or_, ({1}, {1, 2}, {1, 3})) # union
{1, 2, 3}
>>> reduce(operator.and_, ({1}, {1, 2}, {1, 3})) # intersection
{1}
(นอกเหนือจากset
s จริงตัวอย่างของสิ่งเหล่านี้คือวัตถุ Q ของ Django )
ในทางกลับกันหากคุณกำลังติดต่อกับbool
s คุณควรใช้any
และall
:
>>> any((True, False, True))
True
หลังจาก grepping รหัสของฉันดูเหมือนว่าสิ่งเดียวที่ฉันใช้ลดคือการคำนวณแฟกทอเรียล:
reduce(operator.mul, xrange(1, x+1) or (1,))
ฉันกำลังเขียนฟังก์ชันเขียนสำหรับภาษาดังนั้นฉันจึงสร้างฟังก์ชันประกอบโดยใช้การลดร่วมกับโอเปอเรเตอร์ใช้ของฉัน
โดยสรุปการเขียนจะนำรายการฟังก์ชันต่างๆมาประกอบเป็นฟังก์ชันเดียว หากฉันมีการดำเนินการที่ซับซ้อนซึ่งใช้เป็นขั้นตอนฉันต้องการรวมทั้งหมดเข้าด้วยกันดังนี้:
complexop = compose(stage4, stage3, stage2, stage1)
ด้วยวิธีนี้ฉันสามารถนำไปใช้กับนิพจน์ดังนี้:
complexop(expression)
และฉันต้องการให้เทียบเท่ากับ:
stage4(stage3(stage2(stage1(expression))))
ตอนนี้ในการสร้างวัตถุภายในของฉันฉันต้องการพูดว่า:
Lambda([Symbol('x')], Apply(stage4, Apply(stage3, Apply(stage2, Apply(stage1, Symbol('x'))))))
(คลาสแลมบ์ดาสร้างฟังก์ชันที่ผู้ใช้กำหนดเองและใช้สร้างแอปพลิเคชันฟังก์ชัน)
ตอนนี้ลดน่าเสียดายที่พับผิดวิธีดังนั้นฉันจึงใช้ประมาณ:
reduce(lambda x,y: Apply(y, x), reversed(args + [Symbol('x')]))
หากต้องการทราบว่าผลิตผลใดที่ลดลงให้ลองใช้สิ่งเหล่านี้ใน REPL:
reduce(lambda x, y: (x, y), range(1, 11))
reduce(lambda x, y: (y, x), reversed(range(1, 11)))
compose = lambda *func: lambda arg: reduce(lambda x, f: f(x), reversed(funcs), arg)
ในการสร้างชุดที่เป็นไปได้ทั้งหมดของฟังก์ชั่นสำหรับการทดสอบประสิทธิภาพ
สามารถใช้ลดเพื่อรับรายการที่มีองค์ประกอบสูงสุดที่ n
reduce(lambda x,y: x if x[2] > y[2] else y,[[1,2,3,4],[5,2,5,7],[1,6,0,2]])
จะส่งคืน [5, 2, 5, 7] เนื่องจากเป็นรายการที่มีองค์ประกอบสูงสุดที่ 3 +
การลดไม่ จำกัด เฉพาะการดำเนินการสเกลาร์ นอกจากนี้ยังสามารถใช้เพื่อจัดเรียงสิ่งต่างๆลงในถัง (นี่คือสิ่งที่ฉันใช้ลดบ่อยที่สุด)
ลองนึกภาพกรณีที่คุณมีรายการของวัตถุและคุณต้องการจัดระเบียบใหม่ตามลำดับชั้นตามคุณสมบัติที่จัดเก็บไว้ในวัตถุอย่างสม่ำเสมอ ในตัวอย่างต่อไปนี้ฉันสร้างรายการของออบเจ็กต์ข้อมูลเมตาที่เกี่ยวข้องกับบทความในหนังสือพิมพ์ที่เข้ารหัส XML ด้วยarticles
ฟังก์ชัน articles
สร้างรายการองค์ประกอบ XML จากนั้นแมปทีละองค์ประกอบสร้างวัตถุที่เก็บข้อมูลที่น่าสนใจเกี่ยวกับองค์ประกอบเหล่านี้ ในส่วนหน้าฉันจะต้องการให้ผู้ใช้เรียกดูบทความตามส่วน / ส่วนย่อย / พาดหัว ดังนั้นฉันจึงใช้reduce
เพื่อรับรายการบทความและส่งคืนพจนานุกรมเดียวที่สะท้อนถึงลำดับชั้นของส่วน / ส่วนย่อย / บทความ
from lxml import etree
from Reader import Reader
class IssueReader(Reader):
def articles(self):
arts = self.q('//div3') # inherited ... runs an xpath query against the issue
subsection = etree.XPath('./ancestor::div2/@type')
section = etree.XPath('./ancestor::div1/@type')
header_text = etree.XPath('./head//text()')
return map(lambda art: {
'text_id': self.id,
'path': self.getpath(art)[0],
'subsection': (subsection(art)[0] or '[none]'),
'section': (section(art)[0] or '[none]'),
'headline': (''.join(header_text(art)) or '[none]')
}, arts)
def by_section(self):
arts = self.articles()
def extract(acc, art): # acc for accumulator
section = acc.get(art['section'], False)
if section:
subsection = acc.get(art['subsection'], False)
if subsection:
subsection.append(art)
else:
section[art['subsection']] = [art]
else:
acc[art['section']] = {art['subsection']: [art]}
return acc
return reduce(extract, arts, {})
ฉันให้ทั้งสองฟังก์ชั่นที่นี่เพราะฉันคิดว่ามันแสดงให้เห็นว่าแผนที่และการลดสามารถเสริมซึ่งกันและกันได้อย่างไรเมื่อจัดการกับวัตถุ สิ่งเดียวกันนี้สามารถทำได้ด้วย for loop ... แต่การใช้เวลาอย่างจริงจังกับภาษาที่ใช้งานได้มีแนวโน้มที่จะทำให้ฉันคิดในแง่ของแผนที่และลด
ยังไงก็ตามหากใครมีวิธีตั้งค่าคุณสมบัติที่ดีกว่านี้เหมือนที่ฉันทำอยู่extract
ซึ่งอาจยังไม่มีผู้ปกครองของทรัพย์สินที่คุณต้องการตั้งค่าโปรดแจ้งให้เราทราบ
ไม่แน่ใจว่านี่คือสิ่งที่คุณต้องการหรือไม่ แต่คุณสามารถค้นหาซอร์สโค้ดบน Googleได้
ไปที่ลิงก์เพื่อค้นหา'function: reduce () lang: python'ในการค้นหา Google Code
ในตอนแรกโครงการต่อไปนี้ใช้ reduce()
ฯลฯ เป็นต้น แต่สิ่งเหล่านี้แทบไม่น่าแปลกใจเนื่องจากเป็นโครงการขนาดใหญ่
ฟังก์ชันการลดสามารถทำได้โดยใช้ฟังก์ชันการเรียกซ้ำซึ่งฉันเดาว่า Guido คิดว่าชัดเจนกว่า
ปรับปรุง:
เนื่องจากการค้นหาโค้ดของ Google หยุดให้บริการในวันที่ 15 ม.ค. 2555 นอกเหนือจากการเปลี่ยนกลับเป็นการค้นหาปกติของ Google แล้วยังมีสิ่งที่เรียกว่าCode Snippets Collectionที่ดูมีแนวโน้ม มีการกล่าวถึงแหล่งข้อมูลอื่น ๆ ในคำตอบคำถามนี้ (ปิด) การเปลี่ยน Google Code Search? .
อัปเดต 2 (29 พฤษภาคม 2560):
แหล่งที่ดีสำหรับตัวอย่างหลาม (ในรหัสเปิดแหล่งที่มา) เป็นเครื่องมือค้นหา Nullege
for
วนซ้ำ
lang:python "reduce("
ก็จะพบคำจำกัดความreduce
ขึ้นอยู่กับรูปแบบการเข้ารหัสซอร์สโค้ด
import os
files = [
# full filenames
"var/log/apache/errors.log",
"home/kane/images/avatars/crusader.png",
"home/jane/documents/diary.txt",
"home/kane/images/selfie.jpg",
"var/log/abc.txt",
"home/kane/.vimrc",
"home/kane/images/avatars/paladin.png",
]
# unfolding of plain filiname list to file-tree
fs_tree = ({}, # dict of folders
[]) # list of files
for full_name in files:
path, fn = os.path.split(full_name)
reduce(
# this fucction walks deep into path
# and creates placeholders for subfolders
lambda d, k: d[0].setdefault(k, # walk deep
({}, [])), # or create subfolder storage
path.split(os.path.sep),
fs_tree
)[1].append(fn)
print fs_tree
#({'home': (
# {'jane': (
# {'documents': (
# {},
# ['diary.txt']
# )},
# []
# ),
# 'kane': (
# {'images': (
# {'avatars': (
# {},
# ['crusader.png',
# 'paladin.png']
# )},
# ['selfie.jpg']
# )},
# ['.vimrc']
# )},
# []
# ),
# 'var': (
# {'log': (
# {'apache': (
# {},
# ['errors.log']
# )},
# ['abc.txt']
# )},
# [])
#},
#[])
def dump(fname,iterable):
with open(fname,'w') as f:
reduce(lambda x, y: f.write(unicode(y,'utf-8')), iterable)
ฉันเคยreduce
เชื่อมรายการเวกเตอร์การค้นหา PostgreSQLกับ||
โอเปอเรเตอร์ใน sqlalchemy ที่ค้นหาได้:
vectors = (self.column_vector(getattr(self.table.c, column_name))
for column_name in self.indexed_columns)
concatenated = reduce(lambda x, y: x.op('||')(y), vectors)
compiled = concatenated.compile(self.conn)
ฉันมีการใช้ python แบบเก่าของpipegrepที่ใช้การลดและโมดูล glob เพื่อสร้างรายการไฟล์ที่จะประมวลผล:
files = []
files.extend(reduce(lambda x, y: x + y, map(glob.glob, args)))
ฉันพบว่ามันมีประโยชน์ในตอนนั้น แต่มันไม่จำเป็นจริงๆเพราะสิ่งที่คล้ายกันนั้นดีพอ ๆ กันและอาจอ่านได้มากกว่า
files = []
for f in args:
files.extend(glob.glob(f))
files = [glob.glob(f) for f in args]
itertools
โดยใช้flatten()
สูตรจากdocs.python.org/library/itertools.htmlจากนั้นจึงเขียน: files = flatten(glob.glob(f) for f in args)
(และคราวนี้ฉันทดสอบโค้ดก่อนโพสต์และฉันรู้ว่ามันทำงานได้ถูกต้อง)
files = chain.from_iterable(imap(iglob, args))
ที่chain
, imap
จากitertools
โมดูลและglob.iglob
จะเป็นประโยชน์ถ้ารูปแบบจากargs
อาจผลผลิตไฟล์จากหลายไดเรกทอรี
สมมติว่ามีข้อมูลสถิติรายปีที่จัดเก็บรายการเคาน์เตอร์ เราต้องการหาค่า MIN / MAX ในแต่ละเดือนในปีต่างๆ ตัวอย่างเช่นในเดือนมกราคมจะเป็นวันที่ 10 และสำหรับเดือนกุมภาพันธ์จะเป็น 15 เราจำเป็นต้องเก็บผลลัพธ์ไว้ในตัวนับใหม่
from collections import Counter
stat2011 = Counter({"January": 12, "February": 20, "March": 50, "April": 70, "May": 15,
"June": 35, "July": 30, "August": 15, "September": 20, "October": 60,
"November": 13, "December": 50})
stat2012 = Counter({"January": 36, "February": 15, "March": 50, "April": 10, "May": 90,
"June": 25, "July": 35, "August": 15, "September": 20, "October": 30,
"November": 10, "December": 25})
stat2013 = Counter({"January": 10, "February": 60, "March": 90, "April": 10, "May": 80,
"June": 50, "July": 30, "August": 15, "September": 20, "October": 75,
"November": 60, "December": 15})
stat_list = [stat2011, stat2012, stat2013]
print reduce(lambda x, y: x & y, stat_list) # MIN
print reduce(lambda x, y: x | y, stat_list) # MAX
ฉันมีวัตถุที่แสดงถึงช่วงเวลาที่ทับซ้อนกัน (genomic exons) และกำหนดจุดตัดใหม่โดยใช้__and__
:
class Exon:
def __init__(self):
...
def __and__(self,other):
...
length = self.length + other.length # (e.g.)
return self.__class__(...length,...)
จากนั้นเมื่อฉันมีคอลเลกชันของพวกมัน (เช่นในยีนเดียวกัน) ฉันก็ใช้
intersection = reduce(lambda x,y: x&y, exons)
ฉันเพิ่งพบการใช้งานที่มีประโยชน์reduce
: สตริงแยกโดยไม่ต้องถอดตัวคั่น รหัสทั้งหมดมาจากบล็อกการพูดแบบเป็นโปรแกรม นี่คือรหัส:
reduce(lambda acc, elem: acc[:-1] + [acc[-1] + elem] if elem == "\n" else acc + [elem], re.split("(\n)", "a\nb\nc\n"), [])
นี่คือผลลัพธ์:
['a\n', 'b\n', 'c\n', '']
โปรดทราบว่ามันจัดการกับขอบกรณีที่คำตอบยอดนิยมใน SO ไม่ได้ สำหรับคำอธิบายเชิงลึกเพิ่มเติมฉันกำลังเปลี่ยนเส้นทางคุณไปยังบล็อกโพสต์ต้นฉบับ
ใช้การลด () เพื่อดูว่ารายการวันที่ติดต่อกันหรือไม่:
from datetime import date, timedelta
def checked(d1, d2):
"""
We assume the date list is sorted.
If d2 & d1 are different by 1, everything up to d2 is consecutive, so d2
can advance to the next reduction.
If d2 & d1 are not different by 1, returning d1 - 1 for the next reduction
will guarantee the result produced by reduce() to be something other than
the last date in the sorted date list.
Definition 1: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider consecutive
Definition 2: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider not consecutive
"""
#if (d2 - d1).days == 1 or (d2 - d1).days == 0: # for Definition 1
if (d2 - d1).days == 1: # for Definition 2
return d2
else:
return d1 + timedelta(days=-1)
# datelist = [date(2014, 1, 1), date(2014, 1, 3),
# date(2013, 12, 31), date(2013, 12, 30)]
# datelist = [date(2014, 2, 19), date(2014, 2, 19), date(2014, 2, 20),
# date(2014, 2, 21), date(2014, 2, 22)]
datelist = [date(2014, 2, 19), date(2014, 2, 21),
date(2014, 2, 22), date(2014, 2, 20)]
datelist.sort()
if datelist[-1] == reduce(checked, datelist):
print "dates are consecutive"
else:
print "dates are not consecutive"
from functools import reduce
อนุญาตให้โค้ดเดียวกันทำงานบนทั้ง Python 2 และ 3