@[toc]
一、python的类与对象
参考《datawhale——PythonLanguage》、《Python3 面向对象》
1.1 基本概念
对象 = 属性 + 方法
对象是类的实例。换句话说,类主要定义对象的结构,然后我们以类为模板创建对象。类不但包含方法定义,而且还包含所有实例共享的数据
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
- 方法:类中定义的函数</font>。
- 类属性:类里面方法外面定义的变量称为类属性。</font>类属性所属于类对象并且多个实例对象之间共享同一个类属性,说白了就是类属性所有的通过该类实例化的对象都能共享。
class A(): |
局部变量:定义在方法中的变量,只作用于当前实例的类。</font>
实例属性/变量:在类的声明中,属性是用变量来表示的。 实例属性和具体的某个实例对象有关系,只能在自己的对象里面使用,其他的对象不能直接使用,不同实例对象的实例属性不共享。实例变量用 self 修饰,因为self是谁调用,它的值就属于该对象。
class 类名():
__init__(self):
self.name = xx #实例属性- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:改写从父类继承的方法,满足子类的需求
- 继承:派生类(derived class)继承基类(base class)的字段和方法。所以子类自动共享父类之间数据和方法</font>
- 多态:不同对象对同一方法响应不同的行动
- 实例化:创建一个类的实例,类的具体对象。
1.2 主要知识点
1.2.1 类属性和实例属性区别
- 类属性:类外面,可以通过实例对象.类属性和类名.类属性进行调用。类里面,通过self.类属性和类名.类属性进行调用。
- 实例属性 :类外面,可以通过实例对象.实例属性调用。类里面,通过self.实例属性调用。
- 实例属性就相当于局部变量。出了这个类或者这个类的实例对象,就没有作用了。
- 类属性就相当于类里面的全局变量,可以和这个类的所有实例对象共享。
# 创建类对象 |
注意:属性与方法名相同,属性会覆盖方法。
class A: |
1.2.2 self 是什么?
Python 的 self 相当于 C++ 的 this 指针。
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。</font>(对应于该实例,即该对象本身)在调用方法时,我们无需明确提供与参数 self 相对应的参数
class Ball: |
1.2.3 Python 的魔法方法init
类有一个名为init(self[, param1, param2…])的魔法方法,该方法在类实例化时会自动调用。</font>
class Ball: |
1.2.4 继承和覆盖(super()._init_())
派生类(derived class)继承基类(base class)的字段和方法。如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。多继承时基类方法名相同,子类没有指定时,使用靠前的父类的方法。
# 类定义 |
注意:如果上面的程序去掉:people.init(self, n, a, w)</font>,则输出: 说: 我 0 岁了,我在读 3 年级,因为子类的构造方法把父类的构造方法覆盖了。如果继承的方法中含有父类init的属性但是没有在子类中实现,会报错。此时可以
- 调用未绑定的父类方法base class.init(self,*kargs)
- 使用super函数super()._init_()
==多继承时需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,Python 从左至右搜索,调用靠前的类的此方法。==# 另一个类,多重继承之前的准备
class Speaker:
topic = ''
name = ''
def __init__(self, n, t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s" % (self.name, self.topic))
# 多重继承 |
class Sample02(Student, Speaker): |
1.2.5公有和私有
变量名或函数名前加上“__”两个下划线,那么这个函数或变量就会为私有的了。
- 私有属性在类外部无法直接进行访问。
- 私有方法只能在类的内部调用 ,不能在类的外部调用
【例子】类的私有属性实例【例子】类的私有方法实例
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
counter.count() # 2
print(counter.publicCount) # 2
print(counter._JustCounter__secretCount) # 2 Python的私有为伪私有
print(counter.__secretCount) ## 报错,实例不能访问私有变量
# AttributeError: 'JustCounter' object has no attribute '__secretCount'class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('老马的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name : 老马的程序人生
# url : https://blog.csdn.net/LSGO_MYP
x.foo()
# 这是公共方法
# 这是私有方法
x.__foo()#报错,外部不能使用私有方法
# AttributeError: 'Site' object has no attribute '__foo'1.3魔法方法
魔法方法总是被双下划线包围,例如init。魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。
魔法方法的第一个参数应为cls(类方法) 或者self(实例方法): - cls:代表一个类的名称
- self:代表一个实例对象的名称
1.3.1 init\(self[, …])
init\(self[, …]) :构造器,当一个实例被创建的时候调用的初始化方法
1.3.2 new\(cls[, …])
new方法主要是当你继承一些不可变的 class 时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。在一个对象实例化的时候所调用的第一个方法,在调用__init__初始化前,先调用__new__。
__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的参数直接传递给__init__。
__new__对当前类进行了实例化,并将实例返回,传给__init__的self。
但是,执行了__new__,并不一定会进入__init__,只有__new__返回了当前类cls的实例,当前类的__init__才会进入。
1.3.3 del\(self)
- 析构器,当一个对象将要被系统回收之时调用的方法。
大部分时候,Python 的 ARC(自动引用计数,用来回收对象所占用的空间) 都能准确、高效地回收系统中的每个对象。但如果系统中出现循环引用的情况,比如对象 a 持有一个实例变量引用对象 b,而对象 b 又持有一个实例变量引用对象 a,此时两个对象的引用计数都是 1,而实际上程序已经不再有变量引用它们,系统应该回收它们,此时 Python 的垃圾回收器就可能没那么快,要等专门的循环垃圾回收器(Cyclic Garbage Collector)来检测并回收这种引用循环。
1.3.4 算术运算符、反算术运算符、增量赋值运算符、一元运算符
例如以下运算符。详见《PythonLanguage/14. 魔法方法.md》
常见+- */和+= -=等等__add__(self, other)定义加法的行为:+
__sub__(self, other)定义减法的行为:-
一元运算符
__neg__(self)定义正号的行为:+x
__pos__(self)定义负号的行为:-x
__abs__(self)定义当被abs()调用时的行为
__invert__(self)定义按位求反的行为:~x
1.3.5 属性访问
__getattr__(self, name): 定义当用户试图获取一个不存在的属性时的行为。 |
1.3.6 定制序列len()和getitem()
容器类型的协议
- 如果说你希望定制的容器是不可变的话,你只需要定义len()和getitem()方法。
- 如果你希望定制的容器是可变的话,除了len()和getitem()方法,你还需要定义setitem()和delitem()两个方法。
- len\(self)定义当被len()调用时的行为(返回容器中元素的个数)。
- getitem\(self, key)定义获取容器中元素的行为,相当于self[key]。
- setitem\(self, key, value)定义设置容器中指定元素的行为,相当于self[key] = value。
- delitem\(self, key)定义删除容器中指定元素的行为,相当于del self[key]。
【例子】编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数。
class CountList: |
【例子】编写一个可改变的自定义列表,要求记录列表中每个元素被访问的次数。
class CountList: |
1.3.7 迭代器iter\() 与 next\()
- 迭代是 Python 最强大的功能之一,是访问集合元素的一种方式。字符串,列表或元组对象都可用于创建迭代器。
- 迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
- 迭代器有两个基本的方法:iter() 和 next()。
下面两个例子返回的结果是一样的string = 'lsgogroup'
for c in string:
print(c)
for c in iter(string):
print(c)
links = {'B': '百度', 'A': '阿里', 'T': '腾讯'} |
- iter(object) 函数用来生成迭代器。
- next(iterator[, default]) 返回迭代器的下一个项目。iterator表示可迭代对象,default — 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发 StopIteration 异常。
links = {'B': '百度', 'A': '阿里', 'T': '腾讯'} |
把一个类作为一个迭代器使用需要在类中实现两个魔法方法 iter\() 与 next\() 。
把一个类作为一个迭代器使用需要在类中实现两个魔法方法 iter() 与 next() 。
__iter__(self)定义当迭代容器中的元素的行为,返回一个特殊的迭代器对象, 这个迭代器对象实现了 |
class Fibs: |
1.4 扩展知识点
1.4.1 组合
class Turtle: |
1.4.2类的专有方法和内置函数
具体见《datawhale——PythonLanguage》
类的专有方法:
__init__ : 构造函数,在生成对象时调用 |
内置函数:
- issubclass(class, classinfo) 方法用于判断参数 class 是否是类型参数 classinfo 的子类。一个类被认为是其自身的子类。
- isinstance(object, classinfo) 方法用于判断一个对象是否是一个已知的类型,类似type()。
- hasattr(object, name)用于判断对象是否包含对应的属性。
- getattr(object, name[, default])用于返回一个对象属性值。
- setattr(object, name, value)对应函数 getattr(),用于设置属性值,该属性不一定是存在的。
- delattr(object, name)用于删除属性。
- class property([fget[, fset[, fdel[, doc]]]])用于在新式类中返回属性值
二、 基础函数
2.1 Python5个内建高阶函数(map、reduce、filter、sorted/sort、zip)
参考《PythonLanguage/Python高阶函数使用总结.md》