python学习笔记5 面向对象编程

来源:互联网 发布:淘宝类目详细划分 编辑:程序博客网 时间:2024/06/10 06:22

面向对象编程

class Student(object):    pass

class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

传参数的构造函数 第一个参数必须是self,构造函数你仍然可以用默认参数、可变参数和关键字参数。

class Student(object):    def __init__(self, name, score):        self.name = name        self.score = score

访问限制

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

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)

有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量
student 是类名

继承和多态

获取对象信息

type()

isinstance()

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用函数。

dir()

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

getattr()、setattr()以及hasattr(),

仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

也可以获得对象的函数。然后在外面直接调用这个函数

动态添加功能

可以给一个对象动态的添加功能

>>> 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 # 测试结果

MethodType就是给s绑定一个方法。
给一个实例绑定的方法,对另一个实例是不起作用的
为了给所有实例都绑定方法,可以给class绑定方法

>>> def set_score(self, score):...     self.score = score...>>> Student.set_score = MethodType(set_score, None, Student)

使用slots

如果我们想要限制class的属性怎么办?比如,只允许对Student实例添加name和age属性。

>>> class Student(object):...     __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称...

使用__slots__要注意,__slots__定义的属性仅对当前类起作用,对继承的子类是不起作用的:

使用property

之前必须用
对象.setProperty
对象.getProperty

现在希望能用标准的 .操作符进行操作
对象.property = 这样就要用property

class Student(object):    @property    def birth(self):        return self._birth    @birth.setter    def birth(self, value):        self._birth = value    @property    def age(self):        return 2014 - self._birth

birth是读写属性
age是只读属性

多重继承

支持多重继承

定制类

__str__ __repr__也是

类的描述方法

__iter__

如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,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 aFib()[5]

__getattr__

如果一个对象没有被访问的的方法那么就会尝试使用
__getattr__(self, '方法名')来尝试获得属性
这里可以直接返回一些补救措施

__call__

一个对象实例可以有自己的属性和方法,当我们调用实例方法时,我们用instance.method()来调用。能不能直接在实例本身上调用呢?类似instance()?在Python中,答案是肯定的。

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.

元类

type()

动态生成新的类型

>>> def fn(self, name='world'): # 先定义函数...     print('Hello, %s.' % name)...>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class>>> h = Hello()>>> h.hello()Hello, world.>>> print(type(Hello))<type 'type'>>>> print(type(h))<class '__main__.Hello'>

class的名称;
继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

metaclass

我们也可以使用元类动态创建一个类型

# metaclass是创建类,所以必须从`type`类型派生:class ListMetaclass(type):    def __new__(cls, name, bases, attrs):        attrs['add'] = lambda self, value: self.append(value)        return type.__new__(cls, name, bases, attrs)class MyList(list):    __metaclass__ = ListMetaclass # 指示使用ListMetaclass来定制类

当我们写下metaclass = ListMetaclass语句时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.new()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。

new()方法接收到的参数依次是:

当前准备创建的类的对象;

类的名字;

类继承的父类集合;

类的方法集合。

0 0