python笔记3(面向对象)

mac2024-10-04  58

文章目录

一、面向对象编程1、类和实例2、访问限制3、继承和多态4、获取对象信息 二、实例属性和类属性三、面向对象高级编程1、使用`__slots__`方法2、使用`@property`3、多重继承4、定制类5、使用枚举类`Enum()`6、使用元类`metaclass`

一、面向对象编程


面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。把大块函数通过切割成小函数来降低系统的复杂度

面向对象的程序设计把计算机程序视为一组对象的集合,计算机执行的就是一系列消息在各个对象之间传递

面向对象的数据思想是抽象出Class,根据Class创建Instance(实例)

一个Class既包含数据,又包含操作数据的方法

1、类和实例

定义类:

class Student(object):

(object)表示该类从哪个类继承,如果没有合适的继承类,就使用object类(所有类都会继承的类)

创建实例:

类名+()实现:bart = Studen()

通过一个特殊的__init__方法,在创建实例的时候就把一些必须的属性加上去

def __init__(self,name,score):

__init__的第一个参数必须是self,表示创建实例的本身,传入参数self时不需要传

数据封装

在类的内部定义访问数据的函数

方法就是与实例绑定的函数,方法可以直接访问数据的实例

2、访问限制

设为私有来限制访问

class Student(object): def __init__(self): self.__name =name self.__age = age

_name外部可以直接访问,但按约定,不直接进行访问

__name不能被访问的原因是python解释器对外把__name变量改为了_Student__name(不同版本的python改成不同的变量名)

Python本身没有任何机制不阻止你干坏事,一切靠自觉

3、继承和多态

class Dog(Animal):

子类获得父类的全部功能

当子类与父类同时存在相同的方法,子类会覆盖父类的方法

开闭原则:

对扩展开发:允许增加新的子类对修改封闭

4、获取对象信息

(1)type():查看对象类型,返回对应的class类型

基本类型都可以用type()判断

例:type(123)、type('str')

判断基本数据类型可以直接写int、char

``type(123) == int`

一个变量指向函数或者类,也可以用type()判断

例:type(abs)、type(a)

判断一个对象是否是函数(可以使用type模块中定义的常量)

import types def fn(): pass print(type(fn) == types.FunctionsType) print(type(abs) == types.BuiltFunctionType)

(2)isinstance():判断一个对象是否是该类型本身或者位于该类型的父继承链上

判断继承

如果继承关系为:

object->Animal->Dog

a = Animal() d = Dog() isinstance(d,Dog) isinstance(d,Animal)

与type()一样判断基本类型

isinstance('a',str)

判断一个变量是否是某些类型中的一种

isinstance([1,2,3],(list,tuple))

优先使用instance

(3)dir():获取对象的所有属性和方法,返回一个包含字符串的list

直接操作对象的状态,获得对象的方法

获取属性:getattr():getattr(obj,'x')

可以传入default参数,如果参数不存在,返回默认值

getattr(obi,'x',404) #不存在返回404

设置属性:setattr():setattr(obj,'y',19)

查看属性:hasattr():hasattr(obj,'y')

二、实例属性和类属性


实例属性:

实例属性属于各个实例所有,互不干扰

类属性:

类本身绑定属性,在class中直接定义属性,类属性属于类所有,所有实例共享一个属性

不要对实例属性和类属性使用相同的名字,实例属性会将类属性屏蔽掉

三、面向对象高级编程


1、使用__slots__方法

给实例绑定方法

def set_age(self,age): #定义一个函数作为实例方法 self.age = age from types import Methodtype s.set_age = MethodType(set_age,s) #给实例绑定一个方法

给class绑定方法

def set_score(self,score): self.score = score Student.set_score = set_score

**__slots__:**限制该实例的能添加的属性

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

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

想在子类中运用,就需在子类中也定义__slots__,子类允许定义的属性就是自身的__slots__加上父类的__slots__

2、使用@property

定义读写属性:定义getter和setter方法

class Student(object): @property #getter方法 def birth(self): return self._birth @birth.setter #setter方法 def birth(self,value): self._birth = value

定义只读属性:只定义setter方法

class Student(object): @property def age(self): return 2015-self._birth

3、多重继承

MixIn

多重继承:一个子类同时继承多个父类(class Bat(Mammal,Flyable))

MixIn:(mix+in:混入)给一个类增加多个功能(继承多个父类)

优先通过多重继承来组合多个Mixln的功能

4、定制类

__str__:返回字符串

定义__str__方法:

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

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

__str__()返回用户看到的字符串Student object (name:micle)__repr__()返回开发者看到的字符串<__main__.Student object at 0x109afb310>解决办法:__repr__ = __str__

__iter__:循环类

iter:循环

类想被for...in循环,就必须实现一个__iter__()方法,改方法返回一个迭代对象

class Fib(object): def __init__(self): self.a,self.b = 0,1 def __iter__(self): return self #实例本身是迭代对象,故返回自己

__getitem__:类按下标访问元素

item:

按照下标取出元素:__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切片会报错,原因是__getitem__()传入的可能是一个int,也可能是一个切片对象slice

所以需要对传入的参数做判断if isinstance(n,slice)

__getattr__:避免调用类的方法或属性不存在报错

attr:属性

def __getattr__(self,attr) if attr == 'age': return 99 #返回score的值 #return lambda: 25 #也可以返回函数

只有在没有找到属性的情况下,才调用__getattr__

__getattr__()默认返回时None

要让class只响应特定的几个属性,就需要抛出AttributeError(把一个类的所有属性和方法调用全部动态化处理了)

__call__:对实例进行调用

class Student(object): def __init__(self,name): self.name = name def __call__(self): print('.....')

__call__() 还可以定义参数:def __call__(self,age)

判断一个对象能否被调用:

能被调用的对象就是一个Callable对象:callable(Student())

Python的官方文档

5、使用枚举类Enum()

使用Enum()

from enum import Enum

for name,member in Month__members__.item(): print(name,'=>',',',member.value)

value属性则是自动赋值给成员的int常量,默认从1开始

from enum import Enum,unique @nuique class Weekday(Enum)

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

访问枚举类型

可以用成员名引用枚举常量(Weekday.Tue)也可以直接根据value的值获得枚举常量(Weekday(1))

6、使用元类metaclass

type()

查看一个类型或变量的类型

Hello是一个class,它的类型就是`type``

h = Hello(),h是一个实例,它的类型就是classHello

动态创建新的类型

Hello = type('Hello',(object,),dict(hello=fn)) #创建Hello class

要创建一个class对象,type()函数依次传入3个参数:

1、class的名称 #Hello2、继承的父类集合,继承多重继承,注意tuple的单元素写法 3 #(object,)3、class的方法与函数绑定 #decit(hello=fn)

metaclass:控制类的创建行为

1、先定义metaclass

class ListMetaclass(type):

metaclass的类名以Metaclass结尾

metaclass是类的模板,所以必须从type类型派生

2、再创建class

class MyList(list,metaclass=ListMetaclass:

定义类时,需要传入关键字metaclass

3、最后创建实例

最新回复(0)