文章总览图
一、介绍对象
1,封装
- 数据放在列表里面 (数据层面)
- 常用代码段打包成一个函数 (语句层面)
- 对象是模拟真实事件把数据和代码都封装在一起
(1) 静态的特征称为属性,动态的动作称为方法。对象中的属性和方法,在编程中实际是变量 (属性) 和函数 (方法) 。
(2) 生成类对象:
(3) 类相当于玩具的模板,使对象达到量产的效果。类和对象的关系就如同模具和用这个模具制作出的物品之间的关系。
一个类为它的全部对象给出了一个统一的定义,而他的每个对象则是符合这种定义的一个实体,因此类和对象的关系就是抽象和具体的关系。
(4) 定义了对象的属性和方法,但这不是对象,只能称为类对象,需要用类来创建一个真正的对象,也就是实例对象:
(5) 类名以大写字母开头,而函数名以小写字母开头。
(6) 也可以不赋值,例如直接写 Turtle(),创建出一个 Turtle() 类的实例对象,没有任何的引用就被 python 的垃圾回收机制回收了。
2,面向对象的特征
(1) 封装
信息隐蔽技术,是信息更加安全。对外部隐藏对象的工作细节。
python 的列表事实上是一个对象,提供了若干种方法,供我们根据需求调整整个列表。
不知道列表对象里面这些方法是如何实现的,也不知道列表对象里有哪些变量,这就是封装。
封装起来只给我们需要的方法的名字,调用这个名字实现就行,没有告诉我们具体怎么实现的。
(2) 继承
是子类自动共享父类之间数据和方法的机制。
(3) 多态
可以对不同类的对象调用相同的方法,产生不同的结果。
二、面向对象编程
1,self 是什么
(1) 对象的方法都有一个 self 的参数,python 的 self 就相当于 c++ 的 this 指针。
类是图纸,类实例化的对象才是可以住人的房子。根据一张图纸可以设计成千上万的房子,但是都有不同的主人,每个人都只能回自己的家,self 就相当于每个房子的门牌号,有了 self 就可以轻松的找到自己的房子。
python 的 self 就是相同的道理,由同一个类可以生成无数个对象。这些对象都长得很相似,都来源于同一个类的属性和方法。
当对象的方法被调用的时候,对象会将自身作为一个参数传给 self 参数。接受到 self 的时候,python 就知道是哪个对象在调用方法了。
绑定方法,可以认为方法中的 self 其实就是实例对象的唯一标志。
(2) 类的定义的时候,把 self 写进第一个参数。
2,__init__(self) 称为构造方法
(1)
(2) 只要实例化一个对象的时候,那么这个方法在被对象创建的时候自动调用。
实例化对象的时候是可以传入参数的,这些参数会自动传入 __init__(self) 方法中,通过重写这个方法来自定义对象的初始化操作。
3,公有和私有
(1)
(2) 实现类似于私有变量的特征,python 内部采用了这个技术:
(3) python 把双下横线开头的变量改了名,自动改成了:
(4) 通过这样访问隐藏的变量:
(5) python 的私有机制是伪私有,python 的类是没有权限控制的,不像其他编程语言,所以变量是可以被外部调用的。
三、继承
1,被继承的类称为父类,基类或者超类。而继承者称为子类。
2,如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。
3,解决的方式是重写方法的时候,先调用子类的方法。调用未绑定的父类函数:
4,super 函数超级之处在于你不需要明确给出任何基类的名字,它会自动帮您找出所有基类以及对应的方法。
由于你不用给出基类的名字,这就意味着你如果需要改变了类继承关系,你只要改变 class 语句里的父类即可,而不必在大量代码中去修改所有被继承的方法。
5,多重继承
同时继承父类的多个属性和方法。
四、 组合
1,python 继承机制很有用,但容易把代码复杂化以及依赖隐含继承。
因此,经常的时候,我们可以使用组合来代替。在 python 里组合其实很简单,直接在类定义中把需要的类放进去实例化就可以了。实现纵向之间类的关系,就使用继承。
代码:
2,python 的特性支持另一种编程模式,叫做Mix—in。
详细文档地址:https://fishc.com.cn/thread-48888-1-1.html
3,类,类对象和实例对象。
4,如果属性的名字和方法相同,属性会把方法覆盖掉。
例 1:
例 2:
注意:不要试图在一个类里面定义想到的特性与方法名。尽量利用组合机制,利用继承机制来扩展类。用不同的词性来命名。属性名用名词,方法名用动词。
6,什么是绑定?
python 严格要求方法需要有实例才能被调用,这种限制其实就是 python 所谓的绑定概念。
错误写法:
python 严格要求方法需要有实例才能被调用,这种限制其实就是 python 所谓的绑定概念。所以 python 会自动把 aa 对象作为第一个参数传入,所以才会出现 TypeError:“ 需要 0 个参数,但实际传入了 1 个参数 “。
正确写法:
类中定义属性是静态方法,就算类对象被删除了,它们依然是被存放在内存中的。
7,什么时候用继承和组合?
根据实际应用场景确定。简单的说,组合用于“ 有一个 ”的场景中,继承用于“ 是一个 ”的场景中。例如,天上有一个鸟,地上有只狗,这些适合使用组合。青瓜是瓜,鲨鱼是鱼,这些就应该使用继承。
8,类对象是什么时候产生的?
当你这个类定义完的时候,类定义就变成类对象,可以直接通过 “ 类名 . 属性 ” 或者 “ 类名 . 方法名 () ” 引用或使用相关的属性或方法。
9,区分类属性与实例属性。
num 和 count 是类属性(静态变量),x 和 y 是实例属性。大多数情况下,你应该考虑使用实例属性,而不是类属性(类属性通常仅用来跟踪与类相关的值)。
五、一些相关的 BIF
1,判断一个类是否为另一个类的子类。
如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回 True,否则返回 False。
注意:
- 一个类被认为是其自身的子类。
- classinfo 可以是类对象组成的元组,只要 class 与其中任何一个候选类的子类,则返回 True。
- 在其他情况下,会抛出一个 TypeError 异常。
2,使用 isinstance(object, classinfo) 函数,如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回 True,否则返回 False 。
第一个是传入一个实例对象,第二个是传入一个参数检查它是否属于第一个参数的实例对象。
第二参数也可以传入一个元组,元组里面有多个类,一个一个去检查。有的话,返回 Ture,没有的话,返回 False 。
注意:
- 如果 object 是 classinfo 的子类的一个实例,也符合条件。
- 如果第一个参数不是对象,则永远返回 False。
- classinfo 可以是类对象组成的元组,只要 class 与其中任何一个候选类的子类,则返回 True。
- 如果第二个参数不是类或者由类对象组成的元组,会抛出一个 TypeError 异常。
3,测试一个对象里面是否有指定的属性。
注意:属性名一定要有字符串的标志。
4,返回对象指定的属性值,如果指定的属性不存在,如果设置了 default ,会把 default 打印出来,否则抛出异常。
5,可以设置对象中指定属性的值。如果指定的属性不存在,会新建一个新的属性并给它赋值。
6,删除对象中指定的属性。如果存在,就默默执行。如果属性不存在,就抛出异常。
7,property 设置定义好的属性。
8,避免访问对象不存在的属性(不产生异常)。
第一种先使用 hasattr(object, name) 函数判断属性是否存在,如果存在,再访问(第一个参数(object)是对象,第二个参数(name)是属性名的字符串形式)。
第二种方法是直接使用 getattr(object, name[, default]) 函数并设置 default 参数(返回对象指定的属性值,如果指定的属性不存在,返回default(可选参数)的值)。