python有关的知识

1 Python的函数参数传递

看两个例子:

Python

 

1

2

3

4

5

a = 1

def fun(a):

    a = 2

fun(a)

print a  # 1

Python

 

1

2

3

4

5

a = []

def fun(a):

    a.append(1)

fun(a)

print a  # [1]

所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。

这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。(这就是这个问题的重点)

当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.

如果还不明白的话,这里有更好的解释: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference

2 类变量和实例变量

Python

 

1

2

3

4

5

6

7

8

9

class Person:

    name="aaa"

 

p1=Person()

p2=Person()

p1.name="bbb"

print p1.name  # bbb

print p2.name  # aaa

print Person.name  # aaa

类变量就是供类使用的变量,实例变量就是供实例使用的.

这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.

可以看看下面的例子:

Python

 

1

2

3

4

5

6

7

8

9

class Person:

    name=[]

 

p1=Person()

p2=Person()

p1.name.append(1)

print p1.name  # [1]

print p2.name  # [1]

print Person.name  # [1]

参考:http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block

3 字典推导式

可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的:

Python

 

1

d = {key: value for (key, value) in iterable}

4 Python中单下划线和双下划线

Python

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

>>> 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来代替这个名字,以区别和其他类相同的命名.

详情见:http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python

或者: http://www.zhihu.com/question/19754941

5 字符串格式化:%和.format

.format在许多方面看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题:

Python

 

1

"hi there %s" % name

但是,如果name恰好是(1,2,3),它将会抛出一个TypeError异常.为了保证它总是正确的,你必须这样做:

Python

 

1

"hi there %s" % (name,)   # 提供一个单元素的数组而不是一个参数

但是有点丑..format就没有这些问题.你给的第二个问题也是这样,.format好看多了.

你为什么不用它?

· 不知道它(在读这个之前)

· 为了和Python2.5兼容(譬如logging库建议使用%(issue #4))

http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format

6 Python中重载

引自知乎:http://www.zhihu.com/question/20053359

函数重载主要是为了解决两个问题。

1. 可变参数类型。

2. 可变参数个数。

另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。

好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。

那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。

好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。

__new____init__的区别

这个__new__确实很少见到,先做了解吧.

1. __new__是一个静态方法,而__init__是一个实例方法.

2. __new__方法会返回一个创建的实例,而__init__什么都不返回.

3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用.

4. 当创建一个新实例时调用__new__,初始化一个实例时用__init__.

stackoverflow

ps: __metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new____init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.

8 Python中的作用域

Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。

Python 遇到一个变量的话他会按照这样的顺序进行搜索:

本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

9 lambda函数

其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值