[Code] Python简单小知识

1. Python函数参数

1. 位置参数

调用时根据定义参数的顺序传参,如下例:

def fun(a, b):
    return a-b
fun(1, 2)      # 结果为 1-2 = -1

2. 默认参数

定义函数时写入默认参数,即便不传参也不会显示错误,如下例:

def function (param = 0)
    return param

规范: 将默认的、变化不大的写在后面,变化大的参数写在前面

3. 可更改与不可更改参数

所有的变量都可以理解是内存中一个对象的“引用”,而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象,看下例:

a = 1
def fun(a):
    a = 2
print a     # 结果为1,不会随函数调用而更改
a = []
def fun(a):
    a.append(1)
print a     # 结果为[1],随函数调用而更改

4. 可变参数

可变参数在函数调用时自动组装成tuple,直接上栗子:

定义:

def fun(*args):
    pass 

调用方法一:

fun(1,2,3)

调用方法二:

params = [1,2,3]
fun(*params)

5. 关键字参数

关键字参数在函数调用时自动组装成dict, 可不传,也可传入任意个数的关键字参数(必须传入参数名),上栗子:

定义:

def fun(**kwargs):
    return kw 

调用方法一:

fun(city = 'Beijing')  # 返回{'city':'Beijing'}

调用方法二:

fun(gender ='M', job = 'Coder')  # 返回{'gender':'M', 'job':'Coder'}

备注:当传入一个dict时,函数内部对其修改不会影响函数外的dict

6. 命名关键字参数

限制了传入的关键字参数,只接受固定名称参数传入,如下:

def fun(paraA, paraB, *, keyParaA, keyParaB):
    pass

则只有key为keyParaA和keyParaB的关键字函数可以传入。

7. *args and **kwargs

当不确定函数里将要传递多少参数时你可以用*args,相似的,**kwargs允许使用没有事先定义的参数名;
你也可以混着使用,命名参数首先获得参数值然后所有的其他参数都传递给*args**kwargs,命名参数在列表的最前端,如:

def table_things(titlestring, **kwargs)

*args**kwargs可以同时在函数的定义中,但是*args必须在**kwargs前面。

2. Python方法

Python有三种方法,分别是实例方法,静态方法(staticmethod)以及类方法(classmethod),结合下例说明一下这三种方法的区别:

def fun(x):
    print "executing fun(%s)"%(x)

class A(object):
    def fun(self,x):
        print "executing fun(%s,%s)"%(self,x)

    @classmethod
    def class_fun(cls,x):
        print "executing class_fun(%s,%s)"%(cls,x)

    @staticmethod
    def static_fun(x):
        print "executing static_fun(%s)"%x

a=A()

接下来我们来结合栗子对这三种方法做一下讲解。
对于实例方法,在类里每次定义方法的时候都需要绑定一个实例,在上栗中,fun()就是实例方法,它的调用离不开实例,所以我们把实例自己(self) 作为参数传给方法,便能进行方法与实例的绑定;
显然易见,class_fun()就是类方法了,而它则是通过cls来绑定了类;
而静态方法则不需要对谁进行绑定,那么这三种方法在调用时有什么区别呢?

三种方法调用区别.png

3. Python中的下划线

废话不说直接上栗子:

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

__foo__:只是约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突。

_foo:只是约定,用来指定变量私有.程序员用来指定私有变量的一种方式;

__foo:这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名。

4. Python装饰器

1. 两点定义:

  • 前有@,将之后出现的函数作为参数传入
  • 返回作为参数传入的函数

2、 栗子

def log (func):
    @functools.wraps (func)       
    def wrapper (*args, **kw):
        print ( ‘call %s’ %func.name)
        return func (*args, **kw)
    return wrapper
       
@log
def now ( ):
    print (‘2017-05-09’)

3. 说明

在上栗中,调用now()时,now()方法会作为参数传入log()方法,实际上是调用了以now()为参数的log()方法;
上栗的打印内容是:

call now ( ):
2017-05-09

这么解释或许更加专业,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数log(now),返回wrapper()函数。

5. Lambda

Lambda又称匿名函数,当我们需要使用一个简单的且无需重复调用的函数时,就可以使用lambda,优雅又简洁。其使用方法如下例:

lambda 参数 : 返回值

是不是超简单,那看一下具体使用吧:

map( lambda x: x*x, [y for y in range(10)] )

上述代码等价于:

def sq(x):
    return x * x

map(sq, [y for y in range(10)])

使用lambda可以有效减少代码量,这样的写法是将「遍历列表,给遇到的每个元素都做某种运算」的过程从一个循环里抽象出来成为一个函数 map,然后用 lambda 表达式将这种运算作为参数传给 map。Python 之中,类似能用到 lambda 表达式的「高级」函数还有sort,reduce,filter等等。

6. map(),reduce(),filter()

既然说到了lambda,那就不得不提map()、reduce()和filter(),下面就一一介绍一下吧:

1. map()

map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
比如我们有一个函数f(x)=x*x,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下:

map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])

map()传入的第一个参数是f,即需要对列表中的元素进行的操作,第二个参数是迭代列表,返回则是一个新的经过处理后的列表。
map()作为高阶函数,将运算规则抽象了,将列表中的数字转为字符串只需要一行代码:

map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])

2. reduce()

与map()相同,reduce()同样接收两个参数,第一个是函数(这个函数必须接收两个参数),第二个是迭代列表,它的效果如下:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

即列表中的第一个元素与第二个元素作为参数传入f()的返回值,与列表中的第三个元素再次作为参数传入f()......

3. filter()

filter()函数用于过滤序列。
又和map()类似的是,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素,上栗子:

def is_odd(n):
    return n % 2 == 1

filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])

# 结果: [1, 5, 9, 15]

7. Python中的拷贝

上个栗子一目了然:

import copy
a = [1, 2, 3, 4, ['a', 'b']]  #原始对象

b = a  #赋值,传对象的引用
c = copy.copy(a)  #对象拷贝,浅拷贝
d = copy.deepcopy(a)  #对象拷贝,深拷贝

a.append(5)  #修改对象a
a[4].append('c')  #修改对象a中的['a', 'b']数组对象

print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d

输出结果:
a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c =  [1, 2, 3, 4, ['a', 'b', 'c']]
d =  [1, 2, 3, 4, ['a', 'b']]

8. Python中的正则表达式

1.预设元字符

  • \w 匹配任意一个单词字符,包括数字和下划线,等价于[A-Za-z0-9_],例如 a\wc 可以匹配 abc、acc
  • \W 匹配任意一个非单词字符,与 \w 操作相反,它等价于 [^A-Za-z0-9_],例如: a\Wc 可匹配 a!c
  • \s 匹配任意一个空白字符,空格、回车等都是空白字符,例如:a\sc 可以配 a\nc,这里的 \n表示回车
  • \S 匹配任意一个非空白字符
  • \d 匹配任意一个数字,它等价于[0-9],例如:a\dc 可匹配 a1c、a2c ...
  • \D 匹配任意一个非数字

2.基本元字符

  • . 匹配除换行符以外的任意一个字符,例如:"a.c" 可以完全匹配 "abc",也可以匹配 "abcef" 中的 "abc"
  • \ 转义字符,使特殊字符具有本来的意义,例如: 1.2 可以匹配 1.2
  • [...] 匹配方括号中的任意一个字符,例如:a[bcd]e 可以匹配 abe、ace、ade,它还支持范围操作,比如:a到z可表示为 "a-z",0到9可表示为 "0-9",注意,在 "[]" 中的特殊字符不再有特殊意义,就是它字面的意义,例如:[.*]就是匹配 . 或者 *
  • [^...] 字符集取反,表示只要不是括号中出现的字符都可以匹配,例如:a[^bcd]e 可匹配 aee、afe等

3.重复匹配

  • * 重复匹配零次或者更多次
  • ? 重复匹配零次或者一次
  • + 重复匹配1次或者多次
  • {n} 重复匹配n次
  • {n,} 重复匹配至少n次
  • {n, m} 重复匹配n到m次

4.贪婪与非贪婪

  • 贪婪模式 正则表达式重复匹配时,在使整个表达式能得到匹配的前提下尽可能匹配多的字符,我们称之为贪婪模式;
    例如: r"a.*b" 表示匹配 a 开头 b 结尾,中间可以是任意多个字符的字符串,如果用它来匹配 aaabcb,那么它会匹配整个字符串
  • 非贪婪模式 只需要在量词后面加一个问号" ?",在保证匹配的情况下尽可能少的匹配;
    比如刚才的例子,我们只希望匹配 aaab,那么只需要修改正则表达式为 r"a.*?b"

5.正则引擎

  • re.match(pattern, string)
    match方法从字符串的起始位置开始检查,如果刚好有一个子字符串与正则表达式相匹配,则返回一个Match对象,只要起始位置不匹配则退出,返回 None

  • re.search(pattern, string)
    search 方法虽然也是从起始位置开始检查,但是它在起始位置不匹配的时候会一直尝试往后检查,直到匹配为止,如果到字符串的末尾还没有匹配,则返回 None

  • re.findall(pattern, string)
    findall 返回的对象是由匹配的子字符串组成的列表,即使匹配到了也不中断,继续匹配

写了那么多,但每次写正则的时候,我还是会用度娘 =.=

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容