1.类
①定义:
class Student(Object) //括号里面填继承类,如果没有具体的继承类,就写Object
//__innit__方法,和构造方法类似,self指向实例本身,初始化实例的时候不需要传入self这个参数
def __init__(self, name, score):
self.name = name
self.score = score
//在类中定义的方法第一个参数永远是`self`
②访问限制
1.在属性名称的前面加上__
,属性就变成私有变量,外部无法访问。可以通过_Student__name
来访问__name
变量,但是建议不要这么干
2.变量前面加_
的变量,意思就是“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
3.变量名类似__xxx__
的变量是特殊变量,不是私有变量,可以直接访问
2.获取对象信息
①基本类型都可以用type()
判断
type(123)
<type 'int'>
type('123')
<type 'str'>
type(abs)
<type 'builtin_function_or_method'>
type(a)//a是Animal类的一个实例
<class '__main__.Animal'>
type(123) == type(253)
True
Python还把每种type类型都定义好了常量,放在types
模块里:
import types
type('abc') == types.StringType
True
type(u'abc') == type.UnicodeType
True
type(str) == type.TypeType//有种类型就叫TypeType,是所有类型的本身
②isinstance()
isinstance(a,str)//a表示对象,str是判断a是否为str类型
//还可以判断是否为多种类型中的一种
isinstance(a, (str, unicode))
③dir()
如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:
['__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']
类似__xxx__
的属性和方法在Python中是有特殊用途的,比如__len__
方法返回长度,实际上是自动去调用该对象的__len__()
方法len('ABC')
就等价于'ABC.__len__()'
还可以通过getattr()
、setattr
、hasattr
来操纵一个对象的属性
hasattr(obj, 'x') //obj对象有'x'属性吗
serattr(obj, 'y', 19) // 给obj设置一个'y'属性
getattr(obj, 'y') //获取'y'属性
3.使用_slot_
①当我要为一个定义好的类增加一些功能时,可以给实例绑定上属性和方法:
//绑上属性
s = Student()
s.name = 'Jack'
print s.name
Jack
//绑上方法
def set_age(self, age):
self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s, Student)
s.setage(25)
s.age
25
//给一个实例绑定方法不影响其他实例,如果要给所有实例绑定方法,可以给class绑定方法:
Student.set_age = MethodType(set_score, None, Student)
②使用__slots__
限制class的属性
在定义class的时候,定义一个__slots__
变量,来限制这个class能添加的属性
clss Student(object):
__slots__ = ('name', 'age')
//尝试添加属性
s = Student()
s.name = 'Jack'
s.age = '26'
s.score = '99' //以上两个属性都可以绑定,但是绑定`'score'`就会报错,因为`__slots__`里面没有它
注意:__slots__
定义只对当前类起作用,对继承的子类不起作用,除非在子类也定义__slots__
,此时子类可以绑定的属性就包括父类和子类__slots__
中的所有属性
4.使用@property
绑定属性时,假如直接用以上的方法绑定,会把属性直接暴露出去,可以直接修改,不可靠。有一种方法是通过在类里面定义函数来实现设置属性,得到属性,但是调用的时候略显复杂。这时,用@property
装饰器可以把方法变成属性来简单的调用:
class Student(object):
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an interger!')
if value < 0 or value > 100:
raise ValueError('score must be between 0~100!')
self._score = value
s = Student()
s.score = 60 // 实际转化为s.set_score(60)
s.score //实际转化为s.get_score()
60
5.多重继承
当一个类要继承多个类的属性时class(父类1, 父类2)
,父类2及之后的类一般都是需要加入的额外功能,为了更好地看出继承关系,一般把父类2及其之后的类的类名加上后缀Mixin
6.定制类
看教程
7.使用元类
①type()
使用type()
动态创建类:
//定义类中要用的方法
def fn(self, name = 'world'):
print('Hello, %s' %name)
//用type()创建类
Hello = type('Hello', (object,), dict(hello=fn))
//第一个传入的参数是类的`__name__`属性,等于号左边的名字是指向这个类的变量名,一般都取相同; 第二个传入的参数是类要继承的父类名称,用tuple的形式传入,所以只有一个元素时要记得加逗号; 第三个是用dict()将类中要创建的方法和已有函数绑定,想绑定多个时用逗号隔开即可
②元类 metaclass
看教程
8.错误处理
①try
和java相似:
try:
print 'try...'
r = 10 / int('a')
print 'result:', r
except ValueError, e:
print 'ValueError:', e
except ZeroDivisionError, e:
print 'ZeroDivisionError:', e
else:
print 'no error!'
finally:
print 'finally...'
print 'END'
Python的错误都是class
都是从BaseException
类派生的,常见的错误类型和继承关系看下面链接
https://docs.python.org/2/library/exceptions.html#exception-hierarchy
②记录错误
如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。用Python内置的logging
模块就可以记录错误信息:
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except StandardError, e:
logging.exception(e)
main()
print 'END'
结果是:
END
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
File "D:/Workspace/PycharmProjects/test/Test", line 18, in main
bar('0')
File "D:/Workspace/PycharmProjects/test/Test", line 13, in bar
return foo(s) * 2
File "D:/Workspace/PycharmProjects/test/Test", line 9, in foo
return 10 / int(s)
ZeroDivisionError: integer division or modulo by zero
③
用raise
抛出错误
9.单元测试&文档测试
看教程
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00140137128705556022982cfd844b38d050add8565dcb9000