以下是我在python学习过程中,涉及到的关于python面向对象的一些记录,比较零散,如有错误的地方,恳请指教。
python类
在python中声明一个类:
class Student(Person):
#声明'构造函数'(其实是一个用来传参的初始化函数)
def __init__(self, name, score):
self.name = name
self.score = score
#声明自定义函数
def print_score(self):
print self.score
生成该类的一个对象
stu = Student(name='abc', score=12)
python中的属性分为类属性(和python中的静态变量一样,所有对象公用一份),常量(定义在一个.py文件中一般的常量)和对象属性(数据属性),在python中数据属性定义在__init__
方法中
给对象添加属性,或者给属性赋值(类似js,Python允许动态添加实例变量并绑定任何数据,python是一门动态语言)
stu.age = 18
如果要让内部属性不能被外部访问,可以在属性的前面加上,在python中,实例的变量名如果以开头,就变成一个私有变量(private),只有内部可以访问,外部是不能访问的
def __init__(self, name, score):
self.__name = name
self.__score = score
可以给私有变量添加get和set方法
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
给实例添加方法
def set_age(self, age):
self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s, Student) #给实例绑定一个方法
Student.set_age = MethondType(set_age, None, Studet) #给class绑定方法
python中的绑定
python中严格要求,没有实例,方法是不能被调用的。非绑定的方法 可能可以被调用,但实例对象一定要明确给出,才能确保调用成功。然而,不管是否绑定,方法都是它所在的类的固有属性(而不是实例属性),即使它们几乎总是通过实例来调用的。python类中定义的方法,第一个参数self就是要绑定的实例。
继承
继承描述了基类的属性如何“遗传”给派生类。一个子类可以继承它的基类的任何属性,不管 是数据属性还是方法。(私有属性也会被继承,但是无法被访问到)
常用的特殊的类属性
属性名 | 含义 |
---|---|
__name__ | 类名(字符串) |
__doc__ | 文档字符串 |
__bases__ | 所有父类构成的元组(仅能通过类名调用) |
__dict__ | 对象的所有属性(不包含其父类) |
__module__ | 类定义所在的module |
__class__ | 实例对应的类 |
通过继承重写父类的方法,python中没有重载,所以子类的方法名如果和父类一致就会重写父类的方法
__init__()
如果没有在子类中显式定义该方法,在实例创建完成之后会直接调用父类的__init__()
,如果在子类中定义了该方法,则父类中的__init__()
默认不会执行,除非显示调用父类的__init__()
super(className, self).parentFunc()
其父类必须要显示的继承object,才能调用super()。如果不显式继承object 生成的类的type就是 < type ‘classobj’ >, 而不是< type ‘type’ > 这是一个历史遗留问题, 所以我们在声明一个类的时候要显式继承object
def childFunc(self):
super(childFunc, self).parentFunc()
多继承,子类在调用方法的时候会现在自己的类中找,如果找不到就去父类中找,规则是先广度,后深度。在设计类的继承关系时,通常,主线都是单一继承下来的,需要为某个类加入某个功能的时候,才会去用到多继承(Mixin的设计)。
class P1(object):
def foo(self):
print 'from P1'
def bar(self):
print 'bar from P1'
class P2(object):
def foo(self):
print 'from P2'
class C1(P1, P2):
pass
class C2(P1, P2):#这个位置改成P2,P1的时候,GC就不能同时继承c1,c2了。
def bar(self):
print 'bar from C2'
pass
class GC(C1, C2):
pass
if __name__ == '__main__':
c = C1()
c.foo()
c = C2()
c.foo()
gc = GC()
gc.bar()
定制类
列举出一些常用的定制类的方法
__str__()
和java中的toString类似,重新定义toString方法
def __str__(self):
return 'aaa'
__repr__ ()
和上面的方法作用是类似的 用于python交互界面直接输入对象时的输出
__iter__()
如果一个类想被用于for … in 循环 就必须要实现这个方法 该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
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 # 返回下一个值
__getitem__()
可以实现按照下标取值
class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
__getattr__()
当我们访问一个对象不存在的属性时,会调用这个方法,比如,这个对象中没有定义score 当我们访问score属性的时候,就会调用这个方法
__getattr__(self, 'score')
def __getattr__(self, attr):
if attr=='score':
return 99
__call__()
定义__call__()
函数, 对象就变成一个可调用的对象
class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
s = Student('xiaoming')
s()
__call__()
还可以定义参数。对实例进行直接调用就好比对一个函数进行调用一样,所以你完全可以把对象看成函数,把函数看成对象,因为这两者之间本来就没啥根本的区别。
如果你把对象看成函数,那么函数本身其实也可以在运行期动态创建出来,因为类的实例都是运行期创建出来的,这么一来,我们就模糊了对象和函数的界限。
那么,怎么判断一个变量是对象还是函数呢?其实,更多的时候,我们需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象,比如函数和我们上面定义的带有__call()__
的类实例:
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,二十运行时动态创建的。
python对象
python使用对象模型来存储数据,构造任何类型的值都是一个对象
所有python对象都有三个特性:身份, 类型, 值
身份
每个对象都有一个唯一的身份标识自己,任何对象的身份都可以使用内建函数id()来得到,这个值可以被认为是该对象的内存地址
类型
对象的类型决定了该对象可以保存什么类型的值,可以进行什么样的操作,以及遵循什么样的规则。内建函数Type()可以用来查看Python对象的类型,另外,python中类型也是对象(Python是一门面向对象的语言。) Type()的返回值是对象,而不是一个简单的字符串。
值
对象表示的数据项
上面三个特性在对象创建的时候就被赋值,除了值之外,其它两个特性都是只读的。
如果对象支持更新操作,那么它的值就可以改变,否则他的值也是只读的。对象的值是否可以更改被称为对象的可改变性。只要一个对象没有被销毁,这些特性就一直存在。
在python中,类型就是数据类型;类就是类型,实例是对应类型的对象。
标准类型
数字,整型,布尔值,长整型,浮点型,复数型,字符串,列表,元组,字典。
标准数据类型也叫基本数据类型。
其他内建类型
类型,Null对象(None), 文件,集合/固定集合,函数,模块,类。
所有的类也是对象,他的类型是type;type也是所有Python类型的根和所有Python标准类的默认元类(metaclass)。
python中的特殊类型Nonetype,它只有一个值,那就是None.它不支持任何运算,也没有任何内建方法。
实例化过程:person = Pserson()
, python会帮你生成一个对象返回给你,这个对象是该类的一个实例,然后检查__init__(self)
方法是否存在,如果存在,调用该方法,其中self就是第一步生成的对象。如果不存在,调用父类中的__init__()
方法
面向对象相关内建方法
函数名 | 用法 |
---|---|
isinstance(obj1, obj2) | 判断obj1是否是obj2的一个实例 |
hasattr(obj, s) | 判断obj中是否有s这个属性 |
getattr(obj, s) | 返回obj的属性s的值 |
setattr(obj, s, value) | 设置obj中的s属性值为value |
deleteattr(obj, s) | 从obj中删除s这个属性 |
vars(obj) | 它包含了对象存储于其dict中的属性(键)及值,给定对象必须包含dict属性 |
dir()
函数
- dir()作用在实例上(经典类或新式类)时,显示实例变量,还有在实例所在的类及所有它 的基类中定义的方法和类属性。
- dir()作用在类上(经典类或新式类)时,则显示类以及它的所有基类的dict中的内容。 但它不会显示定义在元类(metaclass)中的类属性。
- dir()作用在模块上时,则显示模块的dict的内容。(这没改动)。
- dir()不带参数时,则显示调用者的局部变量。(也没改动)。