1.类(class)与实例(instance)
class Student(object): #创建一个类,继承object
def __init__(self, age): #self只通过类创建后的实例本身,系统会自动变换
self.age= age
#创建实例
king = Student(16) #函数赋给变量是不带括号的。比如a = function
print king.age #返回16
2.访问限制(私有变量)
self.__age = age #在变量前加__,变成私有标量,外部不能直接调用本参数
__xxx__是特殊变量,能直接被访问。
_xxx,能直接访问,但大家默认它为私有变量。
__xxx也能通过_(类名)__xxx直接访问,python没有绝对的限制。
def get_name(self): #要调用,或修改(set_name),在class中定义一个方法。
return self.__name
3.继承与多态
#多态展示
class Animal(object):
def run(self):
print 'Animal is running'
#dog继承Animal,dog是Animal子类,如果子类父类都有相同的run,优先运行子类的。
class Dog(Animal):
def run(self):
print 'Dog is running'
def run_twince(Animal): #参数Animal在这里只是个变量,不代表Animal类。
Animal.run()
Animal.run()
#调用
run_twince(Dog()) #Dog必须+(),因为要创建实力。
#返回
#Dog is running
#Dog is running
4.获取对象信息
#判断类型
type(clas) #clas是一个类,返回<class '__main__.Animal'>
isinstance(dog,Animal) #常用判断类型.dog是否是Animal类型.是的话返回true
dir('ABC') #显示类中的方法
hasattr(obj,'x') #判断obj实例中是否有x属性(变量),有则返回ture
setattr(obj,'y',19) #增加obj实例中一个y属性(变量),并赋值为19
getattr(obj,'y',404) #获取obj实例中y属性(变量的值),打印19,如果'y'不存在,打印404
hasattr和getattr也可以判断和获取方法.
5.使用__slots__(类中绑定可增加的属性)
from types import MethodType #为实例动态增加方法引出的实例
class Student(object):#类
pass
def set_age(self,age):#方法
self.age = age
s=Student() #创建实例s
s.set_age = MethodType(set_age,s,Student) #在实例中增加方法
s.set_age(15) #检验方法
print s.age #检验方
__slot__ = ('a','b') #在类中定义允许动态绑定的属性.
#子类不会继承父类的__slot__,除非子类也有__slot__,这样子类才会绑定子类和父类__slot__中规定有的属性
6使用@property(使查看属性和设置属性更简单)
#留意查看属性和设置属性的方法都是同名
class Student(object):
#这是查看属性
@property
def age(self):
return self.__age
#这是设置属性,如果这部分不写,就只有读属性,无法写
@age.setter
def age(self,age):
self.__age = age
7.多重继承
class a(b,cMixin,dMixin): #继承了b,cMinin和dMixin(cMixin是类名,在c后面+Mixin是为了直观.)
8.定制类(比如__xxx__)
__str__ :用于返回实例自定义信息.方便开发者查看是否使用该实例.
__iter__:(类模拟list的方法{迭代})本实例能返回多个结果,并且能通过迭代输出(next方法)
__getitem__:(类模拟list的方法{查看list元素和切片})本实例能返回多个结果,并通过序号取值和切片.与之对应的还有__setitem__(设置list元素)和__delitem__(删除list元素)
__getattr__:如果类中没有找到用户调用的方法或属性,会在__getattr__下找.
__call__:一旦实例被调用,就自动执行内部__call__函数,让本类创建的实例能像函数那样直接被调用.可通过callable(Student()),[Student()是实例的意思]查看类是否可被调用.
class Student(object):
def __init__(self,age=10,name='noname'):
self.__name= name
self.__age = age
#********__str__**********
def __str__(self): #返回实例信息
return 'Student object(age=%s)' % self.__name
__repr__ == __str__ #__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串
#********__iter__**********
def __iter__(self):#返回迭代对象,返回形式留意next()方法
return self
def next(self):#让输入的age不断+1直到100
self.__age = self.__age+1
if self.__age >100:
raise StopIteration();#age超过100升起错误
return self.__age
#********__getitem__**********
def __getitem__(self,n):
if isinstance(n,int): #如果n为数字(比如[3]),表示取值
for x in range(n): #循环n次
self.__age = self.__age+1
return self.__age
if isinstance(n,slice):#如果n为切片对象(比如[3:7]),表示切片
start = n.start #表示去了[3:7]中的3给start
stop = n.stop
# print start
# print stop
L = []
for x in range((stop-start)):
self.__age = self.__age+1
L.append(self.__age)
return L
#********__getitem__**********
def __getattr__(self,attr):
if attr == 'name':
return 'Who is your daddy?'
#还是没找到就升起属性属性错误
raise AttributeError('\'Student\'has no attribute: \'%s\'' % attr)
#********__call__**********
def __call__(self):
print 'the name you got is \'%s\'' % self.__name
#调用部分
#********__str__**********
print Student(30,'HJC') #返回用户看的,这里是返回Student object(age=HJC)
s = Student(30,'King') #返回开发者看的
print s #返回开发者看的
#********__iter__**********
for x in Student(16):
print x
#********__getitem__**********
f = Student(16)
print f[3:7] #切片,返回[17,18,19,20]
print f[3] #取值,返回23,因为切片时已经将age变成了20,20+3=23
#********__getitem__**********
print s.name #调用__getitem__内的
#print s.hobby #连__getitem__内都没有的
#********__call__**********
f()
9.使用元类(type创类,metaclass动态创建类方法)
def fn(self,name='World'):
print 'hello,%s.' %name
H =type('Hello',(object,),dict(hello=fn))
# 括号内,第一个是class名称Hello,但实际上调用是看=左边那个
# 第二个是继承,格式是tuple
# 最后一个是class内的方法,方法名是hello,方法内容匹配fn
h=H() #创建实例
h.hello() #运行hello方法
h = Student()
#要想通过变量h反推得到类的名字
print h.__class__.__name__
#__class__是指获取h指向的类Student
class B(A):
def __init__(self):
super(B,self).__init__() #super(要寻找哪个类的父类[这里是B的父类],传入的对象[实例自己])
metaclass就是能让开发者在创建class时就创建一些该class内部方法。(详细参考python难点3)
10.错误处理
try:
print '******begin************'
r = 10/0
print '*********end***********(if r=10/0 create error,this will not execute)'
except ZeroDivisionError as e: #as换成逗号也可以
print 'except:',e
else:
print '\'else\' will execute when no error' #没错就执行这命令
finally:
print '\'finally\' must be executed' #有错无错都执行这命令
不暂停程序而记录错误
#添加logging遇到错误就不会退出程序,而是记录程序并继续往下进行
import logging
def foo(s):
return 10/int(s)
def bar(s):
return foo(s)*2
def main():
try:
bar('0')
except StandardError as e:
logging.exception(e)
main() #调用部分
print 'END'
抛出错误(往上一级抛)
try:
10/0 #只是当遇到除数为0的错误时,往上抛raise后面部分
except ZeroDivisionError:
raise ValueError('input error')#最上一级就是打印出来
11.调试
#断言,遇到错误抛出自己想要表达的信息
def foo(s):
n = int(s)
assert n!=0,'n is zero!'#断言(n不等于0),分则抛出断言错误n is zero
return 10/n
def main():
foo('0')
main() #调用部分,返回看到AssertionError:n is zero!
#python -0 hello.py 在调用python解释器时如左加-0,assert部分会被换成pass忽略掉
logging(比断言好用)
import logging
logging.basicConfig(level=logging.INFO) #共有dubug,info,warning,error4等级
#如果等级为warning,就不显示dubug和info中的错误
s='1'
n = int(s)
logging.info('divisor = %d',n) #在调试时,会先显示divisor(除数)=n,再执行print 10/n返回的值
print 10/n
#返回:
#INFO:root:n=1
#10
在调用python解释器时如(python -m pdb hello.py)是逐步调试
①按l,是产看代码
②按n,是执行下一行代码
③p s 随时查看s的变量值
④按q,退出pdb逐步调试
pdb断点方式(需要import pdb)
①在代码中放入pdb.set_trace() #调用方式还是python hello.py
②按c继续下面代码直到再次遇到代码为pdb.set_trace()的断点处.
③同样可用p s命令查看变量s的值
12.自动化单元测试(unittest,和包括setup和teardown)
#调用python解释器是python -m unittest mydict_test
#注意mydict_test后是没.py的
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
def setUp(self): #每个测试方法调用前后是否会打印出setUp...和tearDown...。
print 'setUp..' #作用貌似防止重复代码,还不是太理解,感觉就是开始测试拉和关闭测试拉的意思.
def tearDown(self):
print 'tearDown'
def test_init(self): #必须以test_*开头,否则测试的时候不会被执行
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'] #当获取不存在的key时,抛出keyerror
def test_attrerror(self):
d=Dict()
with self.assertRaises(AttributeError):
value = d.empty
13.文档测试(推荐使用)
class Dict(dict):
'''
>>> d1 = Dict()
>>> d1['x'] =100
>>>d1.x
100
>>>d2 =Dict(a=1,b=2,c='3')
Traceback(most recent call last):
...
KeyError:'empty'
'''
def __init__(self,**kw):
pass
这种测试是,不仅知道代码是什么,而且还是得直到返回的值是什么.