1.mybatis插件机制源码解析
2.MySQL 简单查询语句执行过程分析(四)WHERE 条件
3.python常ç¨ä»£ç ï¼
mybatis插件机制源码解析
引言
本篇源码解析基于MyBatis3.5.8版本。
首先需要说明的是,本篇文章不是mybatis插件开发的教程,而是从源码层面分析mybatis是如何支持用户自定义插件开发的。
mybatis的插件机制,让其扩展能力大大增加。奇安信源码扫描报告比如我们项目中经常用到的PageHelper,这就是一款基于mybatis插件能力开发的产品,它的功能是让基于mybatis的数据库分页查询更容易使用。
当然基于插件我们还可以开发其它功能,比如在执行sql前打印日志、做权限控制等。
正文mybatis插件也叫mybatis拦截器,它支持从方法级别对mybatis进行拦截。pmon源码整体架构图如下:
解释下几个相关概念:
Interceptor拦截器接口,用户自定义的拦截器就是实现该接口。
InterceptorChain拦截器链,其内部维护一个interceptorslist,表示拦截器链中所有的拦截器,并提供增加或获取拦截器链的方法。比如有个核心的方法是pluginAll。该方法用来生成代理对象。
Invocation拦截器执行时的上下文环境,其实就是目标方法的调用信息,包含目标对象、调用的方法信息、参数信息。核心方法是135 源码proceed。该方法的主要目的就是进行处理链的传播,执行完拦截器的方法后,最终需要调用目标方法的invoke方法。
mybatis支持在哪些地方进行拦截呢?你只需要在代码里搜索interceptorChain.pluginAll的使用位置就可以获取答案,一共有四处:
parameterHandler=(ParameterHandler)interceptorChain.pluginAll(parameterHandler);resultSetHandler=(ResultSetHandler)interceptorChain.pluginAll(resultSetHandler);statementHandler=(StatementHandler)interceptorChain.pluginAll(statementHandler);executor=(Executor)interceptorChain.pluginAll(executor);这四处实现的原理都是一样的,我们只需要选择一个进行分析就可以了。
我们先来看下自定义的插件是如何加载进来的,比如我们使用PageHelper插件,通常会在mybatis-config.xml中加入如下的配置:
<plugins><plugininterceptor="com.github.pagehelper.PageInterceptor"><!--configparamsasthefollowing--><propertyname="param1"value="value1"/></plugin></plugins>mybatis在创建SqlSessionFactory的时候会加载配置文件,
publicConfigurationparse(){ if(parsed){ thrownewBuilderException("EachXMLConfigBuildercanonlybeusedonce.");}parsed=true;parseConfiguration(parser.evalNode("/configuration"));returnconfiguration;}parseConfiguration方法会加载包括plugins在内的很多配置,
privatevoidparseConfiguration(XNoderoot){ try{ ...pluginElement(root.evalNode("plugins"));...}catch(Exceptione){ thrownewBuilderException("ErrorparsingSQLMapperConfiguration.Cause:"+e,e);}}privatevoidpluginElement(XNodeparent)throwsException{ if(parent!=null){ for(XNodechild:parent.getChildren()){ Stringinterceptor=child.getStringAttribute("interceptor");Propertiesproperties=child.getChildrenAsProperties();InterceptorinterceptorInstance=(Interceptor)resolveClass(interceptor).getDeclaredConstructor().newInstance();interceptorInstance.setProperties(properties);configuration.addInterceptor(interceptorInstance);}}}pluginElement干了几件事情:
创建Interceptor实例
设置实例的属性变量
添加到Configuration的interceptorChain拦截器链中
mybatis的插件是通过动态代理实现的,那肯定要生成代理对象,生成的绝地 源码逻辑就是前面提到的pluginAll方法,比如对于Executor生成代理对象就是,
executor=(Executor)interceptorChain.pluginAll(executor);接着看pluginAll方法,
/***该方法会遍历用户定义的插件实现类(Interceptor),并调用Interceptor的plugin方法,对target进行插件化处理,*即我们在实现自定义的Interceptor方法时,在plugin中需要根据自己的逻辑,对目标对象进行包装(代理),创建代理对象,*那我们就可以在该方法中使用Plugin#wrap来创建代理类。*/publicObjectpluginAll(Objecttarget){ for(Interceptorinterceptor:interceptors){ target=interceptor.plugin(target);}returntarget;}这里遍历所有我们定义的拦截器,调用拦截器的plugin方法生成代理对象。有人可能有疑问:如果有多个拦截器,tppl源码target不是被覆盖了吗?
其实不会,所以如果有多个拦截器的话,生成的代理对象会被另一个代理对象代理,从而形成一个代理链条,执行的时候,依次执行所有拦截器的拦截逻辑代码。
plugin方法是接口Interceptor的默认实现类,
defaultObjectplugin(Objecttarget){ returnPlugin.wrap(target,this);}然后进入org.apache.ibatis.plugin.Plugin#wrap,
publicstaticObjectwrap(Objecttarget,Interceptorinterceptor){ Map<Class<?>,Set<Method>>signatureMap=getSignatureMap(interceptor);Class<?>type=target.getClass();Class<?>[]interfaces=getAllInterfaces(type,signatureMap);if(interfaces.length>0){ returnProxy.newProxyInstance(type.getClassLoader(),interfaces,newPlugin(target,interceptor,signatureMap));}returntarget;}首先是获取我们自己实现的Interceptor的方法签名映射表。然后获取需要代理的对象的Class上声明的所有接口。比如如果我们wrap的是Executor,就是Executor的所有接口。然后就是最关键的一步,用Proxy类创建一个代理对象(newProxyInstance)。
注意,newProxyInstance方法的第三个参数,接收的是一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用。
我们这里传入的是Plugin类,故在动态运行过程中会执行Plugin的invoker方法。
如果对这一段不是很理解,建议先了解下java动态代理的原理。java动态代理机制中有两个重要的角色:InvocationHandler(接口)和Proxy(类),这个是背景知识需要掌握的。
我们在深入看下上面的getSignatureMap方法,
privatestaticMap<Class<?>,Set<Method>>getSignatureMap(Interceptorinterceptor){ //从Interceptor的类上获取Intercepts注解,说明我们自定义拦截器需要带注解InterceptsinterceptsAnnotation=interceptor.getClass().getAnnotation(Intercepts.class);//issue#if(interceptsAnnotation==null){ thrownewPluginException("No@Interceptsannotationwasfoundininterceptor"+interceptor.getClass().getName());}Signature[]sigs=interceptsAnnotation.value();Map<Class<?>,Set<Method>>signatureMap=newHashMap<>();//解析Interceptor的values属性(Signature[])数组,存入HashMap,Set<Method>>for(Signaturesig:sigs){ Set<Method>methods=MapUtil.computeIfAbsent(signatureMap,sig.type(),k->newHashSet<>());try{ Methodmethod=sig.type().getMethod(sig.method(),sig.args());methods.add(method);}catch(NoSuchMethodExceptione){ thrownewPluginException("Couldnotfindmethodon"+sig.type()+"named"+sig.method()+".Cause:"+e,e);}}returnsignatureMap;}首先需要从Interceptor的类上获取Intercepts注解,说明我们自定义拦截器需要带注解,比如PageHelper插件的定义如下:
<plugins><plugininterceptor="com.github.pagehelper.PageInterceptor"><!--configparamsasthefollowing--><propertyname="param1"value="value1"/></plugin></plugins>0所以我们可以知道,getSignatureMap其实就是拿到我们自定义拦截器声明需要拦截的类以及类对应的方法。
前面说过,当我们调用代理对象时,最终会执行Plugin类的invoker方法,我们看下Plugin的invoker方法,
<plugins><plugininterceptor="com.github.pagehelper.PageInterceptor"><!--configparamsasthefollowing--><propertyname="param1"value="value1"/></plugin></plugins>1Interceptor接口的intercept方法就是我们自定义拦截器需要实现的逻辑,其参数为Invocation,可从Invocation参数中拿到执行方法的对象,方法,方法参数,比如我们可以从statementHandler拿到SQL语句,实现自己的特殊逻辑。
在该方法的结束需要调用invocation#proceed()方法,进行拦截器链的传播。
参考:
blogs.com/chenpi/p/.html
MySQL 简单查询语句执行过程分析(四)WHERE 条件
MySQL WHERE 条件查询执行过程深入解析
MySQL简单查询语句执行系列的第 4 篇深入探讨 WHERE 条件在查询中的作用。我们分为三个部分讲解:WHERE条件的源码结构:MySQL对多层嵌套的WHERE条件进行树状简化,减少处理层级以提高执行效率。
条件判断过程:以示例SQL为例,依次检查Item_cond_or和Item_cond_and的真假,通过逐层比较确定记录是否匹配。
特殊类型字段比较:set、enum和bit字段的特殊比较规则,如find_in_set函数、整数转换和位操作。
1. WHERE条件结构示例:SQL中的where条件形成树状结构,如i1 > and e1 = '成都',会在语法分析阶段合并简化。比较过程示例:读取记录后,逐层检查Item_cond_or,如'e1 = '成都'使用字符串比较函数func进行判断。
3. 特殊字段比较:set字段:以整数形式存储,通过遍历选项判断字符串值是否匹配。
enum字段:整数值直接比较,无需转换。
bit字段:支持整数和二进制比较,包括位操作。
了解更多细节,请继续关注我们接下来的MySQL简单查询语句执行分析系列(五)- 发送数据。python常ç¨ä»£ç ï¼
Pythonä¸ç常ç¨å ç½®å½æ°æåªäºå¢ï¼
ï¼1ï¼Lambdaå½æ°
ç¨äºå建å¿åå½æ°ï¼å³æ²¡æå称çå½æ°ãå®åªæ¯ä¸ä¸ªè¡¨è¾¾å¼ï¼å½æ°ä½æ¯defç®åå¾å¤ãå½æ们éè¦å建ä¸ä¸ªå½æ°æ¥æ§è¡å个æä½å¹¶ä¸å¯ä»¥å¨ä¸è¡ä¸ç¼åæ¶ï¼å°±å¯ä»¥ç¨å°å¿åå½æ°äºã
Lamdbaç主ä½æ¯ä¸ä¸ªè¡¨è¾¾å¼ï¼èä¸æ¯ä¸ä¸ªä»£ç åãä» ä» è½å¨lambda表达å¼ä¸å°è£ æéçé»è¾è¿å»ã
å©ç¨Lamdbaå½æ°ï¼å¾å¾å¯ä»¥å°ä»£ç ç®å许å¤ã
ï¼2ï¼Mapå½æ°
ä¼å°ä¸ä¸ªå½æ°æ å°å°ä¸ä¸ªè¾å ¥å表çææå ç´ ä¸ï¼æ¯å¦æ们å å建äºä¸ä¸ªå½æ°æ¥è¿åä¸ä¸ªå¤§åçè¾å ¥åè¯ï¼ç¶åå°æ¤å½æ°åºæå°å表colorsä¸çææå ç´ ã
æ们è¿å¯ä»¥ä½¿ç¨å¿åå½æ°lamdbaæ¥é åmapå½æ°ï¼è¿æ ·å¯ä»¥æ´å ç²¾ç®ã
ï¼3ï¼Reduceå½æ°
å½éè¦å¯¹ä¸ä¸ªå表è¿è¡ä¸äºè®¡ç®å¹¶è¿åç»ææ¶ï¼reduce()æ¯ä¸ªé常æç¨çå½æ°ã举个ä¾åï¼å½éè¦è®¡ç®ä¸ä¸ªæ´æ°å表ææå ç´ çä¹ç§¯æ¶ï¼å³å¯ä½¿ç¨reduceå½æ°å®ç°ã
å®ä¸å½æ°çæ大çåºå«å°±æ¯ï¼reduce()éçæ å°å½æ°(function)æ¥æ¶ä¸¤ä¸ªåæ°ï¼èmapæ¥æ¶ä¸ä¸ªåæ°ã
ï¼4ï¼enumerateå½æ°
ç¨äºå°ä¸ä¸ªå¯éåçæ°æ®å¯¹è±¡(å¦å表ãå ç»æå符串)ç»å为ä¸ä¸ªç´¢å¼åºåï¼åæ¶ååºæ°æ®åæ°æ®ä¸æ ï¼ä¸è¬ç¨å¨for循ç¯å½ä¸ã
å®ç两个åæ°ï¼ä¸ä¸ªæ¯åºåãè¿ä»£å¨æå ¶ä»æ¯æè¿ä»£å¯¹è±¡;å¦ä¸ä¸ªæ¯ä¸æ èµ·å§ä½ç½®ï¼é»è®¤æ åµä»0å¼å§ï¼ä¹å¯ä»¥èªå®ä¹è®¡æ°å¨çèµ·å§ç¼å·ã
ï¼5ï¼Zipå½æ°
ç¨äºå°å¯è¿ä»£ç对象ä½ä¸ºåæ°ï¼å°å¯¹è±¡ä¸å¯¹åºçå ç´ æå æä¸ä¸ªä¸ªå ç»ï¼ç¶åè¿åç±è¿äºå ç»ç»æçå表
å½æ们使ç¨zip()å½æ°æ¶ï¼å¦æå个è¿ä»£å¨çå ç´ ä¸ªæ°ä¸ä¸è´ï¼åè¿åå表é¿åº¦ä¸æçç对象ç¸åã
pythonå¿ èå ¥é¨ä»£ç æ¯ä»ä¹
pythonå¿ èå ¥é¨ä»£ç å举å¦ä¸ï¼
1ã大å第ä¸ä¸ªåæ¯ã以ä¸ä»£ç åä¼ä½¿ç¨title()æ¹æ³ï¼ä»è大åå符串ä¸æ¯ä¸ä¸ªåè¯çé¦åæ¯ã
s="programmingisawesome"
print(s.title())
#ProgrammingIsAwesome
2ãå符å ç´ ç»æå¤å®ãæ£æ¥ä¸¤ä¸ªå符串çç»æå ç´ æ¯ä¸æ¯ä¸æ ·çã
fromcollectionsimportCounter
defanagram(first,second):
returnCounter(first)==Counter(second)
anagram("abcd3","3acdb")#True
3ãæå°N次å符串ã该代ç åä¸éè¦å¾ªç¯è¯å¥å°±è½æå°N次å符串ã
n=2
s="Programming"
print(s*n)
#ProgrammingProgramming
æ³äºè§£æ´å¤æå ³pythonç详æ ï¼æ¨èå¨è¯¢è¾¾å æè²ãè¾¾å æè²è´åäºé¢åITäºèç½è¡ä¸ï¼å¹å »è½¯ä»¶å¼åå·¥ç¨å¸ãæµè¯å·¥ç¨å¸ãUI设计å¸ãç½ç»è¥éå·¥ç¨å¸ãä¼è®¡çèåºäººæï¼ç®åå·²å¨åä¸æµ·å¹¿æ·±ç个大ä¸åå¸æç«äºå®¶å¦ä¹ ä¸å¿ï¼æ´æ¯ä¸å¤å®¶ä¼ä¸ç¾è®¢äººæå¹å »åè®®ï¼å ¨é¢å©åå¦åæ´å¥½å°±ä¸ãæå ´è¶£çè¯ç¹å»æ¤å¤ï¼å è´¹å¦ä¹ ä¸ä¸
Python常ç¨çæ£å表达å¼å¤çå½æ°è¯¦è§£æ£å表达å¼æ¯ä¸ä¸ªç¹æ®çå符åºåï¼ç¨äºç®æ´è¡¨è¾¾ä¸ç»å符串ç¹å¾ï¼æ£æ¥ä¸ä¸ªå符串æ¯å¦ä¸æç§æ¨¡å¼å¹é ï¼ä½¿ç¨èµ·æ¥ååæ¹ä¾¿ã
å¨Pythonä¸ï¼æ们éè¿è°ç¨reåºæ¥ä½¿ç¨re模åï¼
importre
ä¸é¢ä»ç»Python常ç¨çæ£å表达å¼å¤çå½æ°ã
re.matchå½æ°
re.matchå½æ°ä»å符串çèµ·å§ä½ç½®å¹é æ£å表达å¼ï¼è¿åmatch对象ï¼å¦æä¸æ¯èµ·å§ä½ç½®å¹é æåçè¯ï¼match()å°±è¿åNoneã
re.match(pattern,string,flags=0)
patternï¼å¹é çæ£å表达å¼ã
stringï¼å¾ å¹é çå符串ã
flagsï¼æ å¿ä½ï¼ç¨äºæ§å¶æ£å表达å¼çå¹é æ¹å¼ï¼å¦ï¼æ¯å¦åºå大å°åï¼å¤è¡å¹é ççãå ·ä½åæ°ä¸ºï¼
re.Iï¼å¿½ç¥å¤§å°åã
re.Lï¼è¡¨ç¤ºç¹æ®å符é\w,\W,\b,\B,\s,\Sä¾èµäºå½åç¯å¢ã
re.Mï¼å¤è¡æ¨¡å¼ã
re.Sï¼å³.ï¼å¹¶ä¸å æ¬æ¢è¡ç¬¦å¨å çä»»æå符ï¼.ä¸å æ¬æ¢è¡ç¬¦ï¼ã
re.Uï¼è¡¨ç¤ºç¹æ®å符é\w,\W,\b,\B,\d,\D,\s,\Sä¾èµäºUnicodeå符å±æ§æ°æ®åºã
re.Xï¼ä¸ºäºå¢å å¯è¯»æ§ï¼å¿½ç¥ç©ºæ ¼å#åé¢ç注éã
import?re#ä»èµ·å§ä½ç½®å¹é r1=re.match('abc','abcdefghi')print(r1)#ä¸ä»èµ·å§ä½ç½®å¹é r2=re.match('def','abcdefghi')print(r2)
è¿è¡ç»æï¼
å ¶ä¸ï¼span表示å¹é æåçæ´ä¸ªå串çç´¢å¼ã
使ç¨group(num)ægroups()å¹é 对象å½æ°æ¥è·åå¹é 表达å¼ã
group(num)ï¼å¹é çæ´ä¸ªè¡¨è¾¾å¼çå符串ï¼group()å¯ä»¥ä¸æ¬¡è¾å ¥å¤ä¸ªç»å·ï¼è¿æ¶å®å°è¿åä¸ä¸ªå å«é£äºç»æ对åºå¼çå ç»ã
groups()ï¼è¿åä¸ä¸ªå å«ææå°ç»å符串çå ç»ï¼ä»1å°æå«çå°ç»å·ã
import?res='This?is?a?demo'r1=re.match(r'(.*)?is?(.*)',s)r2=re.match(r'(.*)?is?(.*?)',s)print(r1.group())print(r1.group(1))print(r1.group(2))print(r1.groups())print()print(r2.group())print(r2.group(1))print(r2.group(2))print(r2.groups())
è¿è¡ç»æï¼
ä¸è¿°ä»£ç ä¸ç(.*)å(.*?)表示æ£å表达å¼ç贪婪å¹é ä¸é贪婪å¹é ã
re.searchå½æ°
re.searchå½æ°æ«ææ´ä¸ªå符串并è¿å第ä¸ä¸ªæåçå¹é ï¼å¦æå¹é æååè¿åmatch对象ï¼å¦åè¿åNoneã
re.search(pattern,string,flags=0)
patternï¼å¹é çæ£å表达å¼ã
stringï¼å¾ å¹é çå符串ã
flagsï¼æ å¿ä½ï¼ç¨äºæ§å¶æ£å表达å¼çå¹é æ¹å¼ï¼å¦ï¼æ¯å¦åºå大å°åï¼å¤è¡å¹é ççã
import?re#ä»èµ·å§ä½ç½®å¹é r1=re.search('abc','abcdefghi')print(r1)#ä¸ä»èµ·å§ä½ç½®å¹é r2=re.search('def','abcdefghi')print(r2)
è¿è¡ç»æï¼
使ç¨group(num)ægroups()å¹é 对象å½æ°æ¥è·åå¹é 表达å¼ã
group(num=0)ï¼å¹é çæ´ä¸ªè¡¨è¾¾å¼çå符串ï¼group()å¯ä»¥ä¸æ¬¡è¾å ¥å¤ä¸ªç»å·ï¼è¿æ¶å®å°è¿åä¸ä¸ªå å«é£äºç»æ对åºå¼çå ç»ã
groups()ï¼è¿åä¸ä¸ªå å«ææå°ç»å符串çå ç»ï¼ä»1å°æå«çå°ç»å·ã
import?res='This?is?a?demo'r1=re.search(r'(.*)?is?(.*)',s)r2=re.search(r'(.*)?is?(.*?)',s)print(r1.group())print(r1.group(1))print(r1.group(2))print(r1.groups())print()print(r2.group())print(r2.group(1))print(r2.group(2))print(r2.groups())
è¿è¡ç»æï¼
ä»ä¸é¢ä¸é¾åç°re.matchä¸re.searchçåºå«ï¼re.matchåªå¹é å符串çèµ·å§ä½ç½®ï¼åªè¦èµ·å§ä½ç½®ä¸ç¬¦åæ£å表达å¼å°±å¹é 失败ï¼ère.searchæ¯å¹é æ´ä¸ªå符串ï¼ç´å°æ¾å°ä¸ä¸ªå¹é 为æ¢ã
re.compileå½æ°
compileå½æ°ç¨äºç¼è¯æ£å表达å¼ï¼çæä¸ä¸ªæ£å表达å¼å¯¹è±¡ï¼ä¾match()åsearch()è¿ä¸¤ä¸ªå½æ°ä½¿ç¨ã
re.compile(pattern[,flags])
patternï¼ä¸ä¸ªå符串形å¼çæ£å表达å¼ã
flagsï¼å¯éï¼è¡¨ç¤ºå¹é 模å¼ï¼æ¯å¦å¿½ç¥å¤§å°åï¼å¤è¡æ¨¡å¼çã
import?re#å¹é æ°år=re.compile(r'\d+')?r1=r.match('This?is?a?demo')r2=r.match('This?is??and?That?is?',0,)r3=r.match('This?is??and?That?is?',8,)?print(r1)print(r2)print(r3)
è¿è¡ç»æï¼
findallå½æ°
æç´¢å符串ï¼ä»¥å表形å¼è¿åæ£å表达å¼å¹é çææå串ï¼å¦æ没ææ¾å°å¹é çï¼åè¿å空å表ã
éè¦æ³¨æçæ¯ï¼matchåsearchæ¯å¹é ä¸æ¬¡ï¼èfindallå¹é ææã
findall(string[,pos[,endpos]])
stringï¼å¾ å¹é çå符串ã
posï¼å¯éåæ°ï¼æå®å符串çèµ·å§ä½ç½®ï¼é»è®¤ä¸º0ã
endposï¼å¯éåæ°ï¼æå®å符串çç»æä½ç½®ï¼é»è®¤ä¸ºå符串çé¿åº¦ã
import?re#å¹é æ°år=re.compile(r'\d+')?r1=r.findall('This?is?a?demo')r2=r.findall('This?is??and?That?is?',0,)r3=r.findall('This?is??and?That?is?',0,)?print(r1)print(r2)print(r3)
è¿è¡ç»æï¼
re.finditerå½æ°
åfindall类似ï¼å¨å符串ä¸æ¾å°æ£å表达å¼æå¹é çææå串ï¼å¹¶æå®ä»¬ä½ä¸ºä¸ä¸ªè¿ä»£å¨è¿åã
re.finditer(pattern,string,flags=0)
patternï¼å¹é çæ£å表达å¼ã
stringï¼å¾ å¹é çå符串ã
flagsï¼æ å¿ä½ï¼ç¨äºæ§å¶æ£å表达å¼çå¹é æ¹å¼ï¼å¦æ¯å¦åºå大å°åï¼å¤è¡å¹é çã
import?re?r=re.finditer(r'\d+','This?is??and?That?is?')for?i?in?r:?print?(i.group())
è¿è¡ç»æï¼
re.splitå½æ°
å°ä¸ä¸ªå符串æç §æ£å表达å¼å¹é çå串è¿è¡åå²åï¼ä»¥å表形å¼è¿åã
re.split(pattern,string[,maxsplit=0,flags=0])
patternï¼å¹é çæ£å表达å¼ã
stringï¼å¾ å¹é çå符串ã
maxsplitï¼åå²æ¬¡æ°ï¼maxsplit=1åå²ä¸æ¬¡ï¼é»è®¤ä¸º0ï¼ä¸é次æ°ã
flagsï¼æ å¿ä½ï¼ç¨äºæ§å¶æ£å表达å¼çå¹é æ¹å¼ï¼å¦ï¼æ¯å¦åºå大å°åï¼å¤è¡å¹é çã
import?re?r1=re.split('\W+','This?is??and?That?is?')?r2=re.split('\W+','This?is??and?That?is?',maxsplit=1)?r3=re.split('\d+','This?is??and?That?is?')?r4=re.split('\d+','This?is??and?That?is?',maxsplit=1)?print(r1)print(r2)print(r3)print(r4)
è¿è¡ç»æï¼
re.subå½æ°
re.subå½æ°ç¨äºæ¿æ¢å符串ä¸çå¹é 项ã
re.sub(pattern,repl,string,count=0,flags=0)
patternï¼æ£åä¸ç模å¼å符串ã
replï¼æ¿æ¢çå符串ï¼ä¹å¯ä¸ºä¸ä¸ªå½æ°ã
stringï¼è¦è¢«æ¥æ¾æ¿æ¢çåå§å符串ã
countï¼æ¨¡å¼å¹é åæ¿æ¢çæ大次æ°ï¼é»è®¤0表示æ¿æ¢ææçå¹é ã
import?re?r='This?is??and?That?is?'#?å é¤å符串ä¸çæ°år1=re.sub(r'\d+','',r)print(r1)#?å é¤éæ°åçå符串?r2=re.sub(r'\D','',r)print(r2)
è¿è¡ç»æï¼
å°æ¤è¿ç¯å ³äºPython常ç¨çæ£å表达å¼å¤çå½æ°è¯¦è§£çæç« å°±ä»ç»å°è¿äºï¼å¸æ大家以åå¤å¤æ¯æï¼
pythonå¿ èå ¥é¨ä»£ç æ¯ä»ä¹ï¼pythonå¿ èå ¥é¨ä»£ç æ¯Reversingastringusingslicingmy_string"ABCDE"reversed_string=my_string[::-1]print(reversed_string)ã
å½ä½ å®ä¹ä¸ä¸ªa=3çæ¶åï¼ç³»ç»å¨å åä¸ä¼ç»aä¸ä¸ªå°åï¼èè¿ä¸ªaå°±æ¯ä»£è¡¨ä¸ä¸ªé¨çå·ï¼ç¶åå°3ä½å¨éé¢ï¼å½ä½ è¦è°ç¨açæ¶åï¼å°±ç¸å½äºä½ åäºä¸å¥ï¼å°3ï¼åºæ¥ç©å¿äºï¼å½ä½ æ¹å¥½äºè¿ä¸ªæ¿åä¹åï¼é¨çå·aæ¯ä¸è½æ¹åçï¼ä½ä½å¨éé¢çå°3æ¯å¯ä»¥æ¢äººçï¼æ以称ä¹ä¸ºåéï¼èä¸æ¯æéã
pythonç»å
å¨ç¥ä¹åCSDNçååéï¼ç»å¸¸çå°ãå¬å°ä¸äºpythonåå¦è 说ï¼å¦å®åºç¡è¯æ³åï¼ä¸ç¥é该å¦ä»ä¹ï¼å¦äºä¹ä¸ç¥éæä¹ç¨ï¼ä¸è¸çè«ç¶ã
è¿æ¥ï¼CSDNçå ¬ä¼å·æ¨éäºä¸ç¯å客ï¼é¢ç®å«åãè¿·æï¼Pythonå¦å°ä»ä¹ç¨åº¦å¯ä»¥é¢è¯å·¥ä½ï¼ãï¼çå®åæ äºpythonç¨åºåå¨æé¿è¿ç¨ä¸çä¸äºå°æãä»å¹´å¼å§æ¥è§¦pythonè¿é¨ç¼ç¨è¯è¨ï¼ä»å¹´å¼å§åä¸ä½¿ç¨pythonåºå¯¹ææçå¼åå·¥ä½ï¼ç´è³ä»å¤©ã
å顾èªå·±çå¦ä¹ è¿ç¨ï¼ä¹æ¾ç»éå°è¿æ æ°çå°é¾ï¼ä¹æ¾ç»è¿·è«è¿ãå°æè¿ãæ¬ææå举çè¿ä¸ªæ¨¡åï¼æ¯æå¨å·¥ä½åå¦ä¹ ä¸ç¨è¿çæè æ£å¨å¦ä¹ çï¼ç®æ¯å¯¹èªå·±è¿å»å¹´çå¦ä¹ æ»ç»ãå¸æ对å¤å¨è¿·è«ä¸çç¨åºåææ帮å©ã
pythonå¿ èå ¥é¨ä»£ç æ¯ä»ä¹?å ·ä½å¦ä¸ï¼
1ãå转å符串ï¼
#Reversingastringusingslicing
my_string="ABCDEâ
reversedstring=my_string[::-1]
print(reversed_string)
#output
#EDCBA
2ã使ç¨æ é¢ç±»ï¼
my_string="mynameischaitanyabaweja"
newstring=mystring.title(
print(new_string)
#MyNameIschaitanyaBaweja
3ãæ¥æ¾å符串çå¯ä¸è¦ç´ ï¼
my_string="aavvccccddddeee"
temp_set=set(my_string)
newstring=-join(temp_set)
print(new_string)
4ãè¾åºn次å符串æå表ï¼
n=3
my_string="abcd"my_list=[1,2,3]
print(my_string*n)
print(my_list*n)
importstreamlitasst
5ãå表解æï¼
n=4
my_list=[o]*n#[o,oï¼oï¼o]
6ã两个åéä¹é´ç交æ¢å¼ï¼
original_list=[1,2,3,4]
newlist=[2*xforxinoriginal_list]
print(new_list)
#[2,4,6,8]
Pythonç»å¸¸è¢«ç¨äºWebå¼åãæ¯å¦ï¼éè¿mod_wsgi模åï¼Apacheå¯ä»¥è¿è¡ç¨Pythonç¼åçWebç¨åºãPythonå®ä¹äºWSGIæ ååºç¨æ¥å£æ¥åè°Httpæå¡å¨ä¸åºäºPythonçWebç¨åºä¹é´çéä¿¡ãä¸äºWebæ¡æ¶ï¼å¦Django,TurboGears,web2py,Zopeçï¼å¯ä»¥è®©ç¨åºåè½»æ¾å°å¼åå管çå¤æçWebç¨åºã
å¨å¾å¤æä½ç³»ç»éï¼Pythonæ¯æ åçç³»ç»ç»ä»¶ã大å¤æ°Linuxåè¡ç以åNetBSDãOpenBSDåMacOSXé½éæäºPythonï¼å¯ä»¥å¨ç»ç«¯ä¸ç´æ¥è¿è¡Pythonã
åºç¨èå´ï¼
æä¸äºLinuxåè¡ççå®è£ å¨ä½¿ç¨Pythonè¯è¨ç¼åï¼æ¯å¦UbuntuçUbiquityå®è£ å¨,RedHatLinuxåFedoraçAnacondaå®è£ å¨ã
GentooLinux使ç¨Pythonæ¥ç¼åå®çPortageå 管çç³»ç»ãPythonæ ååºå å«äºå¤ä¸ªè°ç¨æä½ç³»ç»åè½çåºã
éè¿pywinè¿ä¸ªç¬¬ä¸æ¹è½¯ä»¶å ï¼Pythonè½å¤è®¿é®WindowsçCOMæå¡åå ¶å®WindowsAPIã
使ç¨IronPythonï¼Pythonç¨åºè½å¤ç´æ¥è°ç¨.NetFrameworkãä¸è¬è¯´æ¥ï¼Pythonç¼åçç³»ç»ç®¡çèæ¬å¨å¯è¯»æ§ãæ§è½ã代ç éç¨åº¦ãæ©å±æ§å æ¹é¢é½ä¼äºæ®éçshellèæ¬ã
pythonæ°æ代ç æåªäºï¼pythonæ°æ代ç æå¦ä¸ï¼
defnot_emptyï¼sï¼ã
returnsandlenï¼sãstripï¼ï¼ï¼0ã
#returnsandsãstripï¼ï¼ã
#å¦æç´æ¥ååsãstripï¼ï¼é£ä¹så¦ææ¯Noneï¼ä¼æ¥éï¼å 为None没æstripæ¹æ³ã
#å¦æsæ¯Noneï¼é£ä¹Noneandä»»ä½å¼é½æ¯Falseï¼ç´æ¥è¿åfalseã
#å¦æséNoneï¼é£ä¹å¤å®sãtripï¼ï¼æ¯å¦ä¸ºç©ºã
ç¸å ³ç®ä»ã
Python解éå¨æäºæ©å±ï¼å¯ä»¥ä½¿ç¨CæC++ï¼æè å ¶ä»å¯ä»¥éè¿Cè°ç¨çè¯è¨ï¼æ©å±æ°çåè½åæ°æ®ç±»åãPythonä¹å¯ç¨äºå¯å®å¶å软件ä¸çæ©å±ç¨åºè¯è¨ãPython丰å¯çæ ååºï¼æä¾äºéç¨äºå个主è¦ç³»ç»å¹³å°çæºç ææºå¨ç ã
å¹´æï¼è¯è¨æµè¡ææ°çç¼è¯å¨Tiobeå°Pythonå å为æå欢è¿çç¼ç¨è¯è¨ï¼å¹´æ¥é¦æ¬¡å°å ¶ç½®äºJavaãCåJavaScriptä¹ä¸ã