Python学习笔记四:面向对象编程

时间:2023-12-11 16:33:44

一:定义类并创建实例

Python中定义类,通过class关键字,类名开头大写,参数列表为所继承的父类。如果没有需要明确继承的类,则继承object。

使用类来创建对象,只需 类名+() 形式即可,python中没有new创建对象的。

class Person(object):
pass xiaoming = Person()
xiaohong = Person()

二:动态改变的类属性

Python可以在创建实例后,通过实例来添加属性。而不是直接在类中定义好所有属性,并且同一个类的不同对象,可以在运行期间添加不同的属性。

xiaoming = Person()
xiaoming.name = 'Xiao Ming'
xiaoming.gender = 'Male'
xiaoming.birth = '1990-1-1' //给xiaohong加上的属性不一定要和xiaoming相同:
xiaohong = Person()
xiaohong.name = 'Xiao Hong'
xiaohong.school = 'No. 1 High School'
xiaohong.grade = 2

三:在类中定义所有对象的公有属性(实例属性,不同实例内容不同)

虽然对象可以动态地赋予属性,但是同一类的对象有很多属性是公有的,那么这些属性就可以在类中定义,并且可以通过类的构造函数在创建对象时赋值。

可以为类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就在这个方法中定义并赋值公有属性。

需要注意的是:__init__() 方法的第一个参数必须是 self(self相当于this指针),后续参数则可以*指定,和定义函数没有任何区别。而在创建实例时,只需传递后续参数即可。

class Person(object):
def __init__(self,name,gender,birth,job):
self.name=name
self.gender=gender
self.birth=birth
self.job=job xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')

四:Python中的访问权限

Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问。但是,如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性。

(其实,python根本没有权限控制,只能靠约定。我们约定 _XX 变量是私有属性,但其实是可以从外部访问的;我们用 __XX 变量实现私有,其实python底层会把该变量转变为  _ClassName_VarName  的变量名。所以我们仍然可以通过 _ClassName_VarName 的形式访问到类中 __XX形式命名的“私有变量”)

五:类属性(不同实例共享同一属性值)

绑定在类上面的属性,被所有实例共享,通过 类名.属性名 访问。

定义类属性很简单,在定义类时,写在方法外即可。

(注意:操作类变量时,要通过 类名.变量名 来操作,不然不起效)

class Person(object):
count=0
def __init__(self,name):
self.name=name
Person.count=Person.count+1//类名.变量名操作类变量

当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

六:实例方法

实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的。

在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过实例方法调用而获得。

class Person(object):
def __init__(self, name, score)://构造函数
self.name = name
self.score = score
def get_grade(self)://实例函数
return 'A'

七:类方法

类方法被所有实例共用,定义类方法时需要 @classmethod 注解。

@classmethod修饰的方法将绑定到类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls。

    @classmethod
def how_many(cls)://cls相当与类本身
return cls.__count //所以这里相当于 ClassName.属性

(这里区分一下函数与方法:函数是一个代码块,可以在代码中通过  函数名()  的形式调用;

方法也是一个函数,但方法是存在与一个类中的。所以我们称呼类中定义的函数为方法,称呼类外定义的为函数。)

(在Python中,方法也是类的属性之一。所以可以通过  className.方法名  访问这个方法,或把它赋值给某变量func;调用方法则加()即可,如:func()则调用了所赋值的类中的对应方法。)

八:继承

注意两点:一:定义类时,在 类名(继承类列表) 括号中指明继承的父类(继承的父类用 , 分隔)

二:在子类的构造函数中,通过   super(子类名, self).__init__(父类构造函数参数列表) 初始化父类;

class Person(object)://定义父类
def __init__(self, name, gender)://父类构造函数
self.name = name
self.gender = gender class Teacher(Person)://继承父类
def __init__(self, name, gender, course)://子类构造函数
super(Teacher,self).__init__(name,gender)//初始化父类
self.course=course//子类新增的属性

子类中调用父类方法的两种方式:

方法一:
super(子类名,self).父类方法名(args) 方法二:
父类名.方法名(args)

九:类型判断

函数 isinstance(实例,类型) 可以判断一个变量是否属于某个类型。

十:动态语言的多态

在调用类中方法时,实例变量优先从自己所属类型寻找函数,找不到则往继承链上寻找,主要找到就调用。

这是动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用

十一:动态获取对象的详细信息

isinstance(obj,class) 判断它是否是某种类型

type(obj) 函数获取变量的类型

dir(obj) 函数获取变量的所有属性

要获取或者设置对象的具体属性,就需要用 getattr() 和 setattr( )函数

十二:特殊方法(magic method)【前后有两下划线的方法】

python中的类自带了一些特殊方法,如:__str__()/__len__()等。

创建一个Python对象时,实际上进行了两步操作:首先是调用了类中的__new__(cls)方法新建对象,然后调用__init__(args)方法为对象初始化赋值。

__del__()方法是析构方法,用于回收Python对象时调用。

在某些操作,如打印、排序等时,会自动调用默认的特殊方法。如果我们想按自己的思路来实现这些功能,则可以在定义类时,重写这些特殊方法。

常见需要重写的方法有:

__str__():定义该类的对象如何以字符串形式输出

__cmp__():定义该类对象的比较方法,用于排序方法时调用。__cmp__用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。

__slots__(str,str...):定义了该类可以拥有的属性,目的是限制当前类所能拥有的属性,禁止实例动态添加属性。

__call__(参数):call方法可以把类定义为一个可调用对象,直接通过 类名(参数) 即可调用类中定义的call方法。

运算符重载:

比较运算类魔术方法:

Python学习笔记四:面向对象编程

四则运算魔术方法:

Python学习笔记四:面向对象编程

逻辑运算魔术方法:

Python学习笔记四:面向对象编程

在定义好上面的几种运算符魔术方法后,在代码中,对类实例对象的 +-*/,&&,||,==,>,<等符号运算就会自动调用类中重载过的相应魔术方法

类的展现方法重载:

Python学习笔记四:面向对象编程

repr方法是把对象转为机器码字符串,str方法是转为给人看的字符串。

Python学习笔记四:面向对象编程

重写dir方法可以选择性地打印类中的属性,某些重要的属性可以不显示出来。

重写类的属性操作方法:

设置对象属性:__setattr__(self,name,value):注意方法中不能调用自身。

查询对象属性:__getattr__(self,name)

__getattribute__(self,name):重写这个方法的话,最终还是要调用父类的 super(Subclass,self).__getattribute__()来查询属性,否则会递归栈溢出。

删除对象属性:__delattr__(self,name):