这篇文章,我们就来看看一些在日常工作中经常用到的Python技巧。集合开发人员经常忘记P??ython也有集合数据类型,而且每个人都喜欢用列表来处理所有事情。什么是套装?简单地说:集合就是不包含重复元素的无序事物的集合。如果你很好地掌握了集合及其逻辑,那么很多问题都可以得到解决。例如,如何获得出现在单词中的字母?myword="NanananaBatman"set(myword){'N','m','n','B','a','}就这么简单,问题解决,这个例子来自官方文档的Python,不要太惊讶。再举个例子,如何在不重复的情况下获取列表的每个元素?#firstryocaneasilychangesettolistandotherwayaroundmylist=["a","b","c","c"]#let'smakeasesetoutofitmyset=set(mylist)#mysetwillbe:{'a','b','c'}#and,it'salreadyiterablesoyoucando:forelementinmyset:print(element)#butyoucanalsoconvertittolistagain:mynewlist=list(myset)#andmynewlistwillbe:['a','b','c']我们可以看到“c”元素不再重复出现。只有一处需要注意,mylist和mynewlist的元素顺序可能不同:mylist=["c","c","a","b"]mynewlist=list(set(mylist))#mynewlistis:['a','b','c']可以看出两个列表的元素顺序是不一样的。接下来,我们再深入一点。假设一些实体之间存在一对多的关系,更具体的例子:用户和权限。通常,一个用户可以拥有多个权限。现在假设有人要修改多个权限,即同时增加和删除一些权限,这个问题应该怎么解决呢?#thisisthesetofpermissionsbeforechange;original_permission_set={"is_admin","can_post_entry","can_edit_entry","can_view_settings"}#thisisnewsetofpermissions;new_permission_set={"can_edit_settings","is_member","can_view_entry","can_edit_entry"}#nowpermissionstoaddwillbe:new_permission_set.difference(original_permission_set)#whichwillresult:{'can_edit_settings','can_view_entry','is_member'}#Asyoucanseecan_edit_entryisinbothsets;sowedonotneed#toworryabouthandlingit#nowpermissionstoremovewillbe:original_permission_set.difference(new_permission_set)#whichwillresult:{'is_admin','entry_setting},'can_view#andbasicallyit'salsotrue;weswitchedadmintomember,andadd#morepermissiononsettings;andremovedthepost_entrypermission一般来说,不要害怕使用集合,它们可以帮你解决很多问题,更多细节请参考Python官方文档。日历在开发与日期和时间相关的功能时,一些信息可能非常重要,例如给定年份的一个月有多少天。这个问题看似简单,但我认为日期和时间是一个非常难的话题,我认为日历的实现是非常有问题的,它是一场噩梦,因为你需要考虑很多角落案例。那么如何准确地知道一个月有多少天呢?importcalendarcalendar.monthrange(2020,12)#willresult:(1,31)#BUT!youneedtobecarefulhere,为什么?让我们阅读文档:帮助(calendar.monthrange)#Helponfunctionmonthrangeinmodulecalendar:#monthrange(year,month)#Returnweekday(0-6~Mon-Sun)andnumberofdays(28-31)for#year,month.#Asyoucanseethefirstvaluereturnedintupleisaweekday,#notthenumberofthefirstdayforagivenmonth;let'stry#togetthesamefor2021calendar.monthrange(2021,12)(2,31)#SothisbasicallymeansthatthefirstdayofDecember2021isWed#andthelastdayofDecember2021is31(whichisobvious,cause#Decemberalwayshas31days)#let'splaywithFebruarycalendar.monthrange(2021,2)(0,28)calendar.monthrange(2022,2)(1,28)calendar.monthrange(2023,2)(2,28)calendar.monthrange(2024,2)(3,29)calendar.monthrange(2025,2)(5,28)#asyoucanseeithandlednicelytheleapyear;某月的第一天当然很简单,就是初一。但是,“本月的第一天是第X周”,如何使用此信息?您可以轻松找出星期几:calendar.monthrange(2024,2)(3,29)#meansthatFebruary2024startsonThursday#let'sdefinesimplehelper:weekdays=["Monday","Tuesday","Wednesday","Thursday","星期五","星期六","星期日"]#nowwecandosomethinglike:weekdays[3]#willresultin:'Thursday'#nowsimplemathtotellwhatdayis15thofFebruary2020:offset=3#it'sthefirstvaluefrommonthrangefordayinrange(1,29):print(day,weekdays[(day+offset-1)%7])1Thursday2Friday3Saturday4Sunday...18Sunday19Monday20Tuesday21Wednesday22Thursday23Friday24Saturday...28Wednesday29Thursday#whichbasicallymakessense;也许此代码不适合直接用于生产,因为您可以使用datetime更轻松地查找星期几:fromdatetime2ate=2date4timedate(2,15)datetime.weekday(mydate)#willresult:3#or:datetime。strftime(mydate,"%A")'星期四'总的来说,日历模块有很多有趣的特性,值得慢慢学习:#checkingifyearisleap:calendar.isleap(2021)#Falsecalendar.isleap(2024)#True#orcheckinghowmanydayswillbeleapdaysforgivenyearspan:calendar.leapdays(2021,2026)#1calendar.leapdays(2020,2026)#2#readthehelphere,asrangeis:[y1,y2),意思是second#year不包括在内;calendar.leapdays(2020,2024)#1两个参数是的,枚举有第二个参数,许多有经验的开发人员可能不知道。我们来看一个例子:mylist=['a','b','d','c','g','e']fori,iteminenumerate(mylist):print(i,item)#Willgive:0a1b2d3c4g5e#but,youcanaddastartforenumeration:fori,iteminenumerate(mylist,16):print(i,item)#andnowyouwillget:16a17b18d19c20g21e#这两个参数可以指定从哪里开始枚举,比如上面代码中的enumerate(mylist,16)。如果需要处理偏移量,可以考虑这个参数。if-else逻辑你经常需要根据不同的条件处理不同的逻辑。没有经验的开发人员可能会编写类似于以下的代码:OPEN=1IN_PROGRESS=2CLOSED=3defhandle_open_status():print('Handlingopenstatus')defhandle_in_progress_status():print('Handlinginprogressstatus')defhandle_closed_status():print('Handlingclosedstatus')defhandle_status_change(status):ifstatus==OPEN:handle_open_status()elifstatus==IN_PROGRESS:handle_in_progress_status()elifstatus==CLOSED:handle_closed_change(1stat_status_status()handle#Handlingopenstatushandle_status_change(2)#Handlinginprogressstatushandle_status_change(3)#Handlingclosedstatus虽然这段代码看起来还不错,但是如果有超过20个条件怎么办呢?那么,应该怎么办呢?):print('Handlingclosedstatus')handlersE:EN.valuelers.OP{Statushandle_open_status,StatusE.IN_PROGRESS.value:handle_in_progress_status,StatusE.CLOSED.value:handle_closed_status}defhandle_status_change(状态):ifstatusnotinhandlers:raiseException(f'Nohandlerfoundforstatus:{status}')handler=handlers[status]handler()handle_status_change(StatusE.OPEN.value)#Handlingopenstatushandle_status_change(StatusE.IN_PROGRESS.value)#Handlinginprogressstatushandle_status_change(StatusE.CLOSED.value)#Handlingclosedstatushandle_status_change(4)#Willraisetheexception这种模式在Python中很常见,它可以让代码看起来更干净,尤其是当方法非常大,需要处理大量条件时enum模块enum模块提供a一系列处理枚举的实用函数,最有趣的是Enum和IntEnum。让我们看一个例子:fromenumimportEnum,IntEnum,Flag,IntFlagclassMyEnum(Enum):FIRST="first"SECOND="second"THIRD="third"classMyIntEnum(IntEnum):ONE=1TWO=2THREE=3#Nowwecandothingslike:MyEnum.FIRST#
