当前位置: 首页 > 科技观察

揭秘,一些你可能不知道的Python小技巧

时间:2023-03-21 14:11:31 科技观察

本篇文章,我们就来看看一些日常工作中经常用到的Python小技巧。01.集合开发者经常忘记Python也有集合数据类型,而且大家都喜欢什么都用列表。什么是套装?简单地说:集合就是不包含重复元素的无序事物的集合。如果你很好地掌握了集合及其逻辑,那么很多问题都可以得到解决。例如,如何获得出现在单词中的字母?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官方文档。02.Calendar在开发日期时间相关的功能时,有些信息可能非常重要,比如某年的这个月有多少天。这个问题看似简单,但我认为日期和时间是一个非常难的话题,我认为日历的实现是非常有问题的,它是一场噩梦,因为你需要考虑很多角落案例。那么如何准确地知道一个月有多少天呢?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)#103。第二个参数是的,枚举还有第二个参数,很多有经验的开发者可能不知道。让我们看一个例子: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)。如果需要处理偏移量,可以考虑这个参数。04.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_status_status()1)#Handlingopenstatushandle_status_change(2)#Handlinginprogressstatushandle_status_change(3)#Handlingclosedstatus虽然这段代码看起来没那么糟糕,但是如果条件超过20个怎么办?那么,应该怎么办?fromenumimportIntEnumclassStatusE(IntEnum):OPEN=1IN_PROGRESS=2CLOSED=3defhandle_open_status():print('Handlingopenstatus')defhandle_in_progress_status():print('Handlinginprogressstatus')defhandle_closed_status():print('Handlingclosedstatus')handlersE:EN.valuelers.OP{状态handle_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中很常见,它可以让代码看起来更干净,尤其是当方法非常多,需要处理大量条件时05.enummodule的enum模块提供了一系列处理枚举的实用函数,最有趣的是Enum和IntEnum。让我们看一个例子:fromenumimportEnum,IntEnum,Flag,IntFlagclassMyEnum(Enum):FIRST="first"SECOND="second"THIRD="third"classMyIntEnum(IntEnum):ONE=1TWO=2THREE=3#Nowwecandothingslike:MyEnum.FIRST##ithasvalueandname属性,很方便:MyEnum.FIRST.value#'first'MyEnum.FIRST.name#'FIRST'#additionallywecandothingslike:MyEnum('first')#,getenumbyvalueMyEnum['FIRST']#,getenumbyname使用IntEnum写代码也几乎相同,但有一些不同:在大型代码库中,枚举模块在管理常量方面可以提供很大的帮助。枚举的本地化可能有点棘手,但可以做到,我将用django做一个快速演示:fromenumimportEnumfromdjango.utils.translationimportgettext_lazyas_classMyEnum(Enum):FIRST="first"SECOND="second"THIRD="third"@classmethoddefchoices(cls):return[(cls.FIRST.value,_('first')),(cls.SECOND.value,_('second')),(cls.THIRD.value,_('third'))]#Andlaterineg。modeldefiniton:some_field=models.CharField(max_length=10,choices=MyEnum.choices())06.iPythoniPythonisinteractivePython,也就是交互式命令行shell,有点像Python解释器。首先,你需要安装iPython:pipinstallipython接下来,你只需要在输入命令时将Python替换为ipython:#youshouldseesomethinglikethisafteryoustart:Python3.8.5(default,Jul282020,12:59:40)Type'copyright','credits'or'license'fororeinformationIPython7.18.1--AnenhancedInteractivePython.Type'?'forhelp.In[1]:ipython支持很多系统命令,比如ls或者cat,tab键可以显示提示,也可以使用上下键找到以前使用过的订单。有关更多详细信息,请参阅官方文档。