您的位置:首页 > 编程语言 > Python开发

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

2016-12-06 10:20 357 查看
面向对象编程

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 a

Fib()[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()方法接收到的参数依次是:

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

类的名字;

类继承的父类集合;

类的方法集合。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: