名字
Everything is an object. |
Name: 名字。python中一切(除了名字外)都是对象。1,2,“Hello World!”,[],{1:2},类,实例,函数都是对象。是的,没错,1 也是一个对象;类和实例都是对象
名字可以理解为c指针,它的规则像c指针。名字不能理解为“C++的别名”。python没有 aliasing.
x = "Hello World"
系统要做三件事
创建一个str对象,保存"Hello World"
创建一个名字x(如果x名字还未存在)
把x指向对象
name 是没有类别的,是通用的。类别只跟对象有关系。对象除了保存内容外,还保存
- 类别
- 引用计数,如果计数为0,则对象被垃圾回收
变量实际上就是名字,全局变量,局部变量都是名字,全局、局部是名字的可见范围
module: 只是包含许多名字的一个包,相当于命名空间
attribute: 包中的名字是这个包的attribute
Qualification: 找到名字的方法
mod.attr
如
import mod1
mod1.fun
赋值
assign an object to a name,是修改名字的引用x = [1,2,3];
y = x; # x,y 指向同一个对象。也就是共享的引用,指两个引用指向同一个对象。
使用名字指向对象,可以修改对象
x[0] = 3;
y
[3, 2, 3]
== 比较对象内容
is 比较引用(更严格的相等)
但是注意:对于小整数和短字符串对象,python 缓存并重复使用
>>> x = "word" >>> y = "word" # 同一个对象,因为短字符串对象被缓存并重复使用的 >>> x is y True >>> x = (1,2) >>> y = (1,2) # 另一个对象 >>> x is y False >>> x == y True
因为赋值语法 x=... 总是修改x名字的引用,所以不能用它来修改x原先指向的对象。(python 有=操作符重载吗?)
并且注意 x=y,总是使 x,y 指向同一个对象,如果这不是预期的效果,可以使用拷贝代替赋值
• Slice expressions with empty limits (L[:]) copy sequences.
• The dictionary and set copy method (X.copy()) copies a dictionary or set.
• Some built-in functions, such as list, make copies (list(L)).
• The copy standard library module makes full copies.
function
def 是可以执行的代码def 创建一个函数对象,并赋值给一个名字
lambda 创建一个函数对象,并作为返回结果
result 返回一个对象给 caller
yield 返回一个对象给 caller,同时记住了离开时的状态(以备再次继续)
global
nonlocal python3.0 新语法,enclosing def 中定义的名字。enclosing function 可以作为保持状态的场所
名字的scope
变量(变量只是名字)和函数的关系- 在def内定义,为local name, def 外看不到
- 在 enclosing def (the def enclosing current def)内定义,为 nonlocal name. python 3.0 新语法
- 在 def 外定义,为 global name
名字的查找规则 LEGB
local -> Enclosing -> global -> built-in
import
import 不同于c/c++的include(预编译,代码替换),它是运行时的操作。import 可以放在代码的任何地方。只有当代码走到import的位置,才会执行。它完成三项工作- 找到模块文件
- 编译(没有相应的.pyc 或者 .pyc 时间戳比.py 陈旧)
- 运行代码
- b.py
- b.pyc
- b directory (package import)
- b.so b.dll b.pyd (C/C++)
- A compiled built-in module coded in C and statically linked into Python
- A ZIP file component that is automatically extracted when imported
- An in-memory image, for frozen executables
- A Java class, in the Jython version of Python
- A .NET component, in the IronPython version of Python
from mod1 import fun1 # 建立名字fun1,并赋值 fun1 = mod1.fun1
因为上面的区别,所以
# x.py
a = 3
# y.py
from x import a
a = 6
print a #结果为 6
import x
print x.a #结果为 3
如果要改变 x.a 只能用import,而不能用 from import
dir(M) 列出module的所有attributes,除了作者定义的名字,还有系统自动添加的名字
'__builtins__', '__doc__', '__file__', '__name__', '__package__'
__file__ 文件名(在py文件中使用,包含路径)
__name__ 模块名,dir1.dir2.mod
import, from import 两个语句都会执行 mod1,并且在同一个session (process),多次导入mod1只会执行一次。这是预期的效果,两个py文件导入同一个模块,只需执行一次。
如果你要在同一个session再次执行mod1,可以使用
from imp import reload
reload(mod1)
package module
- package module dir1 对应一个文件夹 dir1
- dir1 文件夹中必须有 __init__.py 文件,首次import会执行
- import dir1 和 from dir1 import * 只能看到 __init__.py 中定义的名字,以及 __init__.py 中 __all__ list 里包含的名字
- 要看到其他名字,必须使用 import dir1.mod2 或 from dir1 import mod2; mod2 对应一个 package module dir2 或 file module
- import dir1.dir2.mod1 会执行 dir1/__init__.py, dir1/dir2/__init__.py, dir1/dir2/mod1.py
class
class 和 instance 都是对象
class statement 内的名字为 class attributes
instance 继承了class attributes,但有自己的 namespace
per-instance 名字只能在 def 中赋值,以 self. 开头
class 是 module 的名字
继承
class 继承父类(可以有多个父类)的名字
instance 继承了祖宗类的名字
object.attribute 触发搜索
Each attribute reference triggers a new bottom-up tree search—even references to self attributes within a class’s methods |
class.method(instance, args...)
instance.method(args...)
这两者是等同的,你可以用其中一种形式调用类方法
实际上,python 会自动把第一种形式转化为第二种
参见 ex-class.py
Best practice: 一般都用 instance.method(args...) 除非你要调用名字被覆盖的函数 比如子类__init__调用父类的__init__
# -*- coding: gbk -*- import math class C: num = 0 def __init__(self, x, y=0): self.x = x self.y = y C.num += 1 def mod(self): print "C.mod %.1f"%math.sqrt(self.x**2+self.y**2) def isReal(self): return self.y==0 def __str__(self): return "%.1f+%.1fi"%(self.x,self.y) def howmany(): return num; class Pure(C): def __init__(self, y): C.__init__(self,0,y) #只能用 class.method 方法 def mod(self): print "Pure.mod %.1f"%math.fabs(self.y) def __str__(self): return "%.1fi"%self.y def module(num): num.mod() c1 = C(5) print C.isReal(c1) print c1.isReal() #两种调用方法是相同的 print c1 c2 = Pure(5) print c2.isReal() #继承的父类属性 print c2 # 覆盖父类属性 print C.__str__(c2) #使用被覆盖的父类属性 print Pure.num # 类属性,而非实例的属性 module(c1) #多态 module(c2) #多态结果
True
True
5.0+0.0i
False
5.0i
0.0+5.0i
2
C.mod 5.0
Pure.mod 5.0
delegate
class Base: def delegate(self): self.action() def action(self): raise NotImplementedError('action must be defined!') class Sub(Base): def action(self): print "Yeah, doing action in Sub" c = Base() try: c.delegate() except NotImplementedError as e: print("Failed, because ",e) d = Sub() d.delegate()
运算符重载
多重继承
python 允许多重继承,当碰到子类的一个名字时,搜索顺序- python 2.x 父类依继承定义从左到右,每个父类穷尽其继承树
- python 3.x 深度优先?
多重继承一般用于 mix in 技巧
被 mix in 的父类定义一些方法,子类继承该 mix in 类,继承了这些方法
0 comments:
Post a Comment