模块
一个py文件,就是一个模块(module),相同函数和变量名可以存在不同的模块中。一个py模块就是一个类,可以这么理解
为了避免类的冲突,引入包的概念。注意每一个包下面,都会有一个init.py的文件,他的模块名就是包名
作用域
正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,PI等;
类似_xxx和xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc,abc等;
之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。
命令行运行
在命令行运行py文件时,Python解释器把一个特殊变量name置为main
因此以下代码
1 | if __name__=='__main__': |
在$ python hello.py
运行时,会执行test()
,但是import时不会执行
安装第三方模块
安装pip
使用pip安装,可在命令行检查输入pip,检查是否安装。
如果安装不成功,可以直接去官网地址下载
下载完成之后,解压到一个文件夹,用CMD控制台进入解压目录,输入:1
python setup.py install
然后输入pip命令,检测是否安装成功
安装PIL
PIL是一个图片处理库,而且是跨平台的。
当我们执行以下失败时1
pip install PIL
换成1
pip install pillow
然后引入时fom PIL import Image
在python2中使用python31
2
3
from __future__ import unicode_literals
from __future__ import division
2.x里的字符串用’xxx’表示str,Unicode字符串用u’xxx’表示unicode
在3.x中,所有字符串都被视为unicode,写u’xxx’和’xxx’是完全一致的,但是str就必须写成b’xxx’,来表示“二进制字符串”
面向对象编程
给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法(Method)。这里指明了方法跟函数概念上的区别
数据封装、继承和多态是面向对象的三大特点。
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线,在Python中,实例的变量名如果以开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
继承和多态1
2
3
4
5
6
7
8
9
10
11
12
13
14#父类
class Animal(object):
def run(self):
print "Animal is running"
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
dog.run()
cat = Cat()
cat.run()
type()
,来判断对象类型。通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。
dir()
,来获得一个对象的所有属性跟方法。
高级特性:多重继承,定制类,元类
动态绑定
动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现
以下给一个实例绑定方法,其他实例没有这个方法:1
2
3
4
5
6
7
8# 给dog对象动态新增方法set_age
def set_age(self,age): #定义一个函数作为实例方法
self.age = age
dog.set_age = MethodType(set_age,dog,Dog)# 给实例绑定一个方法
dog.set_age(25)
print 'dog的age:%s' % dog.age
以下是给对象绑定方法,它的所有实例都会有这个方法1
2
3
4
5
6
7
8def set_price(self,price): #定义一个函数作为实例方法
self.price = price
Animal.set_price = MethodType(set_price,None,Animal)# 给类绑定一个方法
dog.set_price('200$')
cat.set_price('300$')
print dog.price
print cat.price
@property
类似java的get set,避免把属性直接暴露1
2
3
4
5
6
7
8
9class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
多重继承
区别于java的单继承1
2
3
4class Dog(Mammal, RunnableMixin, CarnivorousMixin):
pass
这样Dog类就继承了Mammal类,RunnableMixin类,CarnivorousMixin类
定制类__str__
__repr__
用法:1
2
3
4
5
6class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name=%s)' % self.name
__repr__ = __str__
__iter__
用法:
如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
__getattr__
利用完全动态的getattr写一个链式调用
1 | class Chain(object): |
__call()__
可以使对象被当成函数进行调用
使用元类
- type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的
type()函数既可以返回一个对象的类型,又可以创建出新的类型
1
2
3
4
5def fn(self, name='world'): # 先定义函数
print('Hello, %s.' % name)
Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
h = Hello()
h.hello()metaclass
控制类的创建行为,还可使使用这个,元类
先定义metaclass,就可以创建类,最后创建实例。所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。
调试
- try catach
- assert 断言,类似于print,输出内容
- logging.info(),可以指定输出的级别
1
2import logging
logging.basicConfig(level=logging.INFO)
单元测试
被测试文件mydict.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# -*- coding:utf-8 -*-
# 单元测试
class Dict(dict):
def __init__(self, **kw):
super(Dict, self).__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
我们需要写的测试代码mydict_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38# -*- coding:utf-8 -*-
# 进行单元测试
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEquals(d.a, 1)
self.assertEquals(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEquals(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEquals(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError):
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
def setUp(self):
print 'setUp...开始测试'
def tearDown(self):
print 'tearDown...测试结束'