python面向对象高级编程_python面向对象高级编程

python中属性和方法的动态绑定

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36class Student(object):

pass

# 实例化一个对象

s = Student()

# 给这个对象绑定一个属性name

s.name = 'John'

print(s.name)

John

# 定义一个方法

def set_age(self, age):

self.age = age

# 导入模块

from types import MethodType

#给s这个对象绑定一个set_age的方法

s.set_age = MethodType(set_age, s)

s.set_age = 30

s.age

25

# 给实例对象绑定的方法只对该实例有效。

# 给所有的实例绑定方法的做法是给类绑定方法

def set_score(self, score):

self.score = score

Student.set_score = MethodType(set_score, Student)

# 给类绑定方法后,所有实例均可调用

python中的__slots__变量

__slots__变量的作用就是限制该类实例能添加的属性:

1

2class Student(object):

__slots__ = ('name', 'age')

在创建Student实例的时候只能动态绑定name和age这两个属性。

__slots__定义的属性仅对当前类实例起作用,对继承的子类不起作用。

[email protected]

@property是python内置的装饰器,它的作用就是把一个方法变成属性访问。1

2

3

4

5

6

7

8

9

10

11class 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 integer!')

if value<0 or value>100:

raise ValueError('score must between 0 ~ 100!')

self._score = value

1

2

3

4s = Student()

s.score = 60 # 实际转化为s.set_score(60)

s.score # 实际转化为s.get_score()

60

只定义getter方法,不定义setter方法就是一个只读属性1

2

3

4

5

6

7

8

9

10class Student(object):

@property

def birth(self):

return self._birth

@birth.setter

def birth(self, value):

self._birth = value

@property

def age(self):

return 2015 - self._birth

birth有读写,age是只读

python的多重继承

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20class Animal(object):

pass

class Mammal(Animal):

pass

class Bird(Animal):

pass

class Dog(Mammal):

pass

class Bat(Mammal):

pass

class Parrot(Bird):

pass

class Ostrich(Bird):

pass

class Runnable(object):

def run(self):

print("Running...")

class Flyable(object):

def fly(self):

print("Flying...")

类的多继承

1

2

3

4class Dog(Mammal, Runnable):

pass

class Bat(Mammal, Flyable):

pass

python中的MixIn

MixIn的作用就是为了更好地看出继承关系,目的就是给一个类增加多个功能,这样在设计类的时候,我们有限考虑通过多重继承来组合多个MixIn的功能 ,而不是设计多层次的复杂的继承关系。

python自带库使用MixIn的实例举例:

TCPSserver和UDPServer要同时服务多个用户就必须使用多进程或多线程模型。这两种模型由ForkingMixIn和ThreadingMixIn提供。

多进程的TCP服务:

1

2class MyTCPServer(TCPServer, ForkingMixIn):

pass

多线程的UDP服务:

1

2class MyUDPServer(UDPServer, ThreadingMixIn):

pass

更先进的协程模型,编写一个CoroutineMixIn:

1

2class MyTCPServer(TCPServer, CoroutineMixIn):

pass

python定制类

1

2

3

4

5class Student(object):

def __init__(self, name):

self.name = name

def __str__(self):

return 'Student object (name: %s)' % self.name

1

2print(Student('Michael'))

Student object (name: Michael)

1

2

3s = Student('Michael')

s

0x345ldf05d

直接显示变量调用的不是__str__(),而是__repr__()。

__str__()和__repr__()的区别是:__str__()返回用户看到的字符串,__repr__()返回程序开发者看到的字符串__repr__()是为调试服务的。

1

2

3

4

5

6class Student(object):

def __init__(self, name):

self.name = name

def __str__(self):

return 'Student object (name=%s)' % self.name

__repr__ = __str__

一个类想被用于for循环中,必须实现一个__iter__()方法,返回一个迭代对象,然后for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到StopIteration退出循环。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21class Fib(object):

def __init__(self):

self.a, self.b = 0, 1

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)

1

1

2

3

5

.

.

.

46368

如果想把一个类表现成list那样取出元素,需要实现__getitem__()方法:

1

2

3

4

5

6class Fib(object):

def __getitem__(self, n):

a, b = 1, 1

for x in range(n):

a, b = b, a+b

return a

如果这个类实现的__getitem__()方法,就可以把这个类当成list来操作,但是需要判断__getitem__()方法传入的参数的类型。 该参数可能是一个int,也可能是一个切片对象slice。 需要对该参数做判断。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19class 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

if start is None:

start = 0

a, b = 1, 1

L = []

for x in range(stop):

if x >= start:

L.append(a)

a, b = b, a+b

return L

1

2

3

4

5f = Fib()

f[0:5]

[1,1,2,3,5]

f[:10]

[1,1,2,3,5,8,13,21,34,55]

对一个__getitem__()方法的参数做判断。并对此进行做其他工作。对step的处理,对负数的处理,等等。

__getattr__():该方法动态返回一个属性。

当调用一个不存在的属性的时候,python会试图调用__getattr__(self, 'score')来尝试获得属性。

__call__()方法直接在实例本身上调用,直接对实例调用。

1

2

3

4

5

6

7

8

9class 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.

__call__()定义参数。

判断一个变量是对象还是函数,更多的时候我们判断一个对象是否能被调用。能被调用的对象就是一个callable对象。

python的枚举类

定义一个枚举类:

1

2from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

枚举类的使用:

直接使用Month.Jan来引用一个常量,或者枚举它的所有成员。

1

2for name, member in Month.__members__.items():

print(name, '=>', member, ',', member.value)

1

2

3

4

5

6

7

8

9

10form enum import Enum, unique

@unique

class Weekday(Enum):

Sun = 0

Mon = 1

Tue = 2

Wed = 3

Thu = 4

Fri = 5

Sat = 6

@unique装饰器保证没有重复值。

python使用元类

type()函数可以查看一个类型或变量的类型,还可以创建出新的类型。

通过type()函数创建一个class对象需传入3 个参数:

class的名称。

继承的父类集合,注意python的多继承。

class的方法名称与函数绑定,1

2

3

4

5

6

7

8

9

10def fn(self, name='world'):

print('Hello, %s.' % name)

Hello = type('Hello', (object,), dict(hello=fn))

h = Hello()

h.hello()

print(type(Hello))

print(type(h))

metaclass的作用就是控制类的创建行为。

我们想创建类就必须根据metaclass创建出类,先定义metaclass,再创建类。

metaclass允许你创建类或修改类

元类使用的实例:

1

2

3

4

5# 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)

有了ListMetaclass,我们在定义类的时候还是要指示使用ListMetaclass来定制类,传入关键字参数metaclass:

1

2class MyList(list, metaclass=ListMetaclass):

pass

在创建MyList类的时候要通过ListMetaclass.__new__()来创建,我们可以修改类的定义,加上新的方法,返回修改后的定义。

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

当前准备创建的类的对象

类的名字

类继承的父类集合

类的方法集合

一般情况下不会遇到metaclass,在使用ORM的时候总会遇到需要通过metaclass修改类定义的。

ORM--object relational mapping,对象-关系映射。就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样写代码更简单,不用直接操作sql语句。

要编写一个ORM框架,所有的类都只能动态定义,因为只有使用者才能根据表的结构定义出对应的类来。

一个简单的ORM框架实例:

1

2

3

4

5

6

7

8

9

10

11class User(Model):

# 定义类的属性到列的映射

id = IntegerField('id')

name = StringField('username')

email = StringField('email')

password = StringField('password')

# 创建一个实例

u = User(id = 123, name='Michael', [email protected]', password='my-pwd')

# 保存到数据库

u.save()

按上面的接口来实现该ORM

1

2

3

4

5

6class Field(object):

def __init__(self, name, column_type):

self.name = name

self.column_type = column_type

def __str__(self):

return '' % (self.__class__.__name__, self.name)

定义各种类型的Field

1

2

3

4

5

6

7class StringField(Field):

def __init__(self, name):

super(StringField, self).__init__(name, 'varchar(100)')

class IntegerField(Field):

def __init__(self, name):

super(IntegerField, self).__init__(name, 'bigint')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值