python学习心得(三)
一,面向对象编程
1,类和实例,
class Student(object):#括号里面的是继承的类
def __init__(self, name, score):初始化对象时,参数个数
self.name = name
self.score = score
def print_score(self):
print '%s: %s' % (self.name, self.score)
2,访问限制
1,如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
2,但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法,,好处:可以对参数做检查,避免传入无效的参数:
lass Student(object):
def __init__(self, name, score):
self.__name = name #双下划线,外部无法直接访问
self.__score = score
def print_score(self):
print '%s: %s' % (self.__name, self.__score)
def set_score(self, score): #通过set_来做筛选
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score')
def get_name(self): #通过get_来获取参数
return self.__name def get_score(self):
return self.__score
3,继承和多态
1,继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;默认继承object
2,有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收;如猫,狗等都属于动物,即为一种多态表现
4,获取对象信息
1,type方法;
>>> import types
>>> type(int)==types.TypeType
True
>>> type(int)
<type 'type'>
>>> type(int)==type(str)
True
2,isinstance()方法:>>> isinstance('abc',str) True
3,dir():获取对象所有方法和属性
>>> dir('o1')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
(二),面向对象编程
1,绑定
对象和类动态绑定属性和方法:
>>> class Student(object):
... pass
...
>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>> print s.name
Michael
>>> def set_age(self, age): # 定义一个函数作为实例方法
... self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25
>>> def set_score(self, score):
... self.score = score
...
>>> Student.set_score = MethodType(set_score, None, Student)
>>> s.set_score(100)
>>> s.score
100
>>> s2.set_score(99)
>>> s2.score
99
# 关键方法MethodTypes(方法名,对象(所有为None),类名)
2,限制
但是,如果我们想要限制class的属性怎么办?比如,只允许对Student实例(而非对象)添加name和age属性。
除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__
>>> class Student(object):
... __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
...
>>> class GraduateStudent(Student):#新建子类,子类可以为继承父类的__slots__
# 除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__。 如添加__slots__=('sex'),即子类被限制为name,age,sex了
... pass
...
>>> g = GraduateStudent()
>>> g.score = 9999
3,@property
作用:既能检查参数,又可以用类似属性这样简单的方式来访问类的变量,即对参数二次开发。
class Student(object):
@property #相当于 score.getter 表示读
def score(self):
return self._score @score.setter #对属性进行先验,附加条件 表示写
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999) #get raise异常
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
4,多重继承
继承的方法按照深度优先的情况选择:如
class Grandfa(object):
def hair(self):
print 'no hair' class Father(Grandfa):
pass class Mother(Grandfa):
def hair(self):
print 'long hair' class Tom(Father,Mother):
pass me = Tom()
me.hair()
# 输出long hair
关系从上到下为:object→Grandfa→father and mother →Tom:深度优先遍历顺序为:Tom→father(没有hair方法)→mother(有hair方法,返回值,遍历结束) 相当于先左子树,再右子树,最后父类寻找方式。
5,定制类
1,__str__和__repr__():两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。
>>> class student(object):
... def __str__(self):
... return 'is str'
... def __repr__(self):
... return 'is repr'
...
>>> s=student()
>>> s
is repr
>>> print s
is str
# 通常__str__()和__repr__()代码都是一样的
2,__iter__:如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环
__getitem__:可以按下标获取指定值,或可以向集合一样切片
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def next(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration();
return self.a # 返回下一个值
>>> for n in Fib():
... print n
...
class Fib(object):
def __getitem__(self, n):
if isinstance(n, int):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice):
start = n.start
stop = n.stop
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
>>> f = Fib()
>>> f[0:5]
[1, 1, 2, 3, 5]
3,__getattr__:防止正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错的情况,
4,__call__:任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用。__call__()还可以定义参数,判断一个对象是否能被调用。
class Student(object):
def __init__(self, name):
self.name = name def __call__(self):
print('My name is %s.' % self.name)
>>> s = Student('Michael')
>>> s()
My name is Michael.
>>> callable(max)
True #能被调用
>>> callable([1, 2, 3])
False #不能被调用
6,使用元类
:不会碰到需要使用metaclass的情况,暂不了解
(三) 错误调试
1,错误处理
try...except...finally...:finally重会执行:但是finally如果有,则一定会被执行(可以没有finally语句)
raise:raise语句抛出一个错误的实例,print异常,代价大,增加吞吐量,所以用raise抛出即可
抛出异常:如果程序中出现了异常,没有办法将具体的异常打印出来,不做任何处理
捕获异常:如果程序出现了异常,就能够详细的打印是什么原因导致了异常并且能够做出相应的处理,能够显示详细的Log
logging:出错,但程序打印完错误信息后会继续执行,并正常退出。
try:
foo()
except StandardError, e:
print 'StandardError'
except ValueError, e:
print 'ValueError'
# StandardError是ValueError,的父类,所以第二个except永远也捕获不到,子类要重写父类中的方法,如果父类的方法有异常声明,子类异常小于等于父类异常
2,调试
1,assert 断言 来辅助查看的地方
# err.py
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n def main():
foo('')
#
$ python err.py
Traceback (most recent call last):
...
AssertionError: n is zero!
#关闭assert python -O err.py, 按默认情况抛异常
2,logging 日志相关操作
import logging
logging.basicConfig(level=logging.INFO)#它允许你指定记录信息的级别,有debug,info,warning,error等几个级别
s=''
n=int(s)
logging.info('n =%d' %n)
print 10/n
#通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。
3,单元测试
单元测试可以有效地测试某个程序模块的行为,是未来重构代码的信心保证。
单元测试的测试用例要覆盖常用的输入组合、边界条件和异常。
单元测试代码要非常简单,如果测试代码太复杂,那么测试代码本身就可能有bug。
单元测试通过了并不意味着程序就没有bug了,但是不通过程序肯定有bug。
#测试功能
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
#测试函数
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 if __name__ == '__main__':
unittest.main()
# 测试原理还是不太清楚,以后有需要再去了解下
python -m unittest mydict_test
.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s OK
4,文档测试
doctest非常有用,不但可以用来测试,还可以直接作为示例代码。通过某些文档生成工具,就可以自动把包含doctest的注释提取出来。用户看文档的时候,同时也看到了doctest。
class Dict(dict):
'''
Simple dict but also support access as x.y style. >>> d1 = Dict()
>>> d1['x'] = 100
>>> d1.x
100
>>> d1.y = 200
>>> d1['y']
200
>>> d2 = Dict(a=1, b=2, c='3')
>>> d2.c
'3'
>>> d2['empty']
Traceback (most recent call last):
...
KeyError: 'empty'
>>> d2.empty
Traceback (most recent call last):
...
AttributeError: 'Dict' object has no attribute 'empty'
''' 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 if __name__=='__main__':
import doctest
doctest.testmod()
# python Dict.py 没结果输出,表示运行正常。
python学习心得(三)的更多相关文章
- python学习心得第三章
python学习心得第三章 1.三元运算 变量=值1 if 条件 else 值2 由图如果条件成立则赋值1给变量,如果条件不成立则赋值2给变量. 2.数据类型 集合:set() class set(o ...
- python学习心得第五章
python学习心得第五章 1.冒泡排序: 冒泡是一种基础的算法,通过这算法可以将一堆值进行有效的排列,可以是从大到小,可以从小到大,条件是任意给出的. 冒泡的原理: 将需要比较的数(n个)有序的两个 ...
- python学习心得第四章
python 学习心得第四章 1.lambda表达式 1:什么是lambda表达式 为了简化简单函数的代码,选择使用lambda表达式 上面两个函数的表达式虽然不一样,但是本质是一样的,并且lamb ...
- python学习第三次记录
python学习第三次记录 python中常用的数据类型: 整数(int) ,字符串(str),布尔值(bool),列表(list),元组(tuple),字典(dict),集合(set). int.数 ...
- Python 学习 第三天 课后总结:
PYTHON学习第三天课后总结: 1,注释:就是对代码起到说明注解的作用. 注释分为单行注释与多行注释. 单行注释:只注释一行代码在需要注释的所在行的行首使用#号来注释此行,注意#与代码之间需要 ...
- Python学习(三) 八大排序算法的实现(下)
本文Python实现了插入排序.基数排序.希尔排序.冒泡排序.高速排序.直接选择排序.堆排序.归并排序的后面四种. 上篇:Python学习(三) 八大排序算法的实现(上) 1.高速排序 描写叙述 通过 ...
- Python学习-第三天-面向对象编程基础
Python学习-第三天-面向对象编程基础 类和对象 简单的说,类是对象的蓝图和模板,而对象是类的实例.这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的 ...
- 获奖感想和python学习心得
一,获奖感想 很荣幸能成为小黄杉的获得者,也很感谢老师对我的这份鼓励和期望.回顾本学期的python学习中,我从一名对编程一无所知的小白,成为一名刚入门的程序猿.首先,我要感谢我的任课老师娄嘉鹏老师, ...
- python 学习(三)
按照上次python 学习(二)的思路,第一步要实现从一个网站的页面上自动获取指定列表中的信息.折腾数日,得到一段可以正常运行的代码,如下: #web2.py import re import url ...
- Python学习心得体会总结,不要采坑
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:樱桃小丸子0093 大家要持续关注哦,不定时更新Python知识 ...
随机推荐
- POJ 2195 Going Home | 带权二分图匹配
给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...
- java中的Timer
一个java中用Timer做的简单定时器小程序. package com.test.lx; import java.util.TimerTask; public class TimeTaskTest ...
- What is a Microsoft Failover Cluster Virtual Adapter
What is a Microsoft Failover Cluster Virtual Adapter anyway? A question often asked is, "What i ...
- Java并发容器--ConcurrentHashMap
引子 1.不安全:大家都知道HashMap不是线程安全的,在多线程环境下,对HashMap进行put操作会导致死循环.是因为多线程会导致Entry链表形成环形数据结构,这样Entry的next节点将永 ...
- PriorityQueue详解(一)
在Java SE 5.0中,引入了一些新的Collection API,PriorityQueue就是其中的一个.今天由于机缘巧合,花了一个小时看了一下这个类的内部实现,代码很有点意思,所以写下来跟大 ...
- sqlalchemy多表查询
from datetime import datetime from sqlalchemy import Column,Integer,String,Boolean,DateTime,ForeignK ...
- OpenGL 之 坐标变换
http://www.cnblogs.com/irvinow/archive/2009/11/20/1606496.html 创建OpenGL模型过程: OPENGL坐标变换很有特点,为了简单描述先定 ...
- (十)Linux查看系统信息的一些命令及查看已安装软件包的命令
转自:http://cheneyph.iteye.com/blog/824746 系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看 ...
- ubuntu14.04LTS openssh-server 手动安装配置步骤
先用能上网的机器下载:zlib-1.2.5.tar.bz2.openssh-5.6p1.tar.gz.openssl-0.9.8o.tar.tar,接下来,准备安装. 步骤如下: 1.首先解压安装zl ...
- Visual Studio跨平台开发(1):Hello Xamarin!
前言 应用程序发展的脚步, 从来没有停过. 从早期的Windows 应用程序, 到网络时代的web 应用程序, 再到近几年相当盛行的行动装置应用程序(Mobile Application), 身为C# ...