python学习--初识面向对象
类的相关知识
类:具有相同属性和方法的一类事物
对象:类的具体体现
函数vs面向对象
函数:
封装一个功能
类:
封装多个相关联的功能,功能的集合。
抽象,站在上帝的角度考虑。
公共的模板。
类的结构:
class 类名:
name1 = 'python' 静态属性
def __init__(self,name,age):
self.name=name #self.name 对象的属性名
self.age=age
def func(self): 方法
pass
类名:
操作属性
1,查看类中全部的属性及方法 __dict__
类名.__dict__
2,对某个属性进行删改查,以及增加某个属性,万能的 点.
类名.age = 20
类名.name = 'baidu'
del 类名.name
类名.name
操作方法 尽量不用类名操作方法
类名.func(111)
对象的相关知识
实例化对象
obj = 类名('baidu',20) 实例化过程,实例化一个对象
内部经历了三个阶段:
1,在内存中开辟一个对象空间,只有一个类对象指针。
2,自动执行__init__方法,并将对象空间传给self。
3,给对象空间封装相应的属性。
1,对象操作对象的属性:
1,查看对象的中的所有属性。__dict__
obj.__dict__
2,操作对象中的属性。
obj.name 查
obj.sex = '男' 增
obj.name = 'bing'改
del obj.name 删
2,对象查看类中的属性。
obj.name1
3, 对象执行类中的方法:
obj.func()
类名.func(obj)
对象之间的交互
对象与对象之间可不可互相调用?
同一个类实例化出来的对象之间是不能互相访问的。
不同类实例化的对象有可能互相访问。
类命名空间与对象、实例的命名空间
只要对象的某个属性被直接赋值,那么一定是对象的命名空间发生变化
只要是静态变量,就用类名操作
对象为什么能调用类中的属性与方法而且只是调用,不能改变?
先从自己空间去找,没有此属性他会通过类对象指针从类去找,类中找不到,会从父类去找。
若它进行改变操作,它就会在自己的对象空间里创建相同的名字的属性或方法。
所以对象只能查看类中的属性,不能增删改类中的属性。
类能不能调用对象的属性?
不能
类的组合用法
组合: 给一个类的对象封装一个属性,这个属性是另一个类的对象。
组合的意义:让类的对象与另一个类的对象产生关系,类与类之间产生关系。
面向对象的三大特性
继承
提高代码的重用性,规范代码(要就继承父类的子类都实现相同的方法:抽象类、接口)
当你开始编写两个类的时候,出现了重复的代码,通过继承来简化代码,把重复的代码放在父类中
继承和抽象 两个概念
继承:继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。
抽象:抽象即抽取类似或者说比较像的部分。
抽象分成两个层次:
1.将具体对象比较像的部分抽取成类;
2.将多个类比较像的部分抽取成父类。
** 继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。**
单继承
语法 : 父类 子类
class ParentClass1: #定义父类
pass
class ParentClass2: #定义父类
pass
class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
pass
class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
pass
继承与重用
重用性 :减少代码的重复,子类可以复用父类的方法
在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时
我们不可能从头开始写一个类B,这就用到了类的继承的概念。
通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用
提示:用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大生了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.
子类可以使用父类中的名字(变量和方法)
# 1
# 在子类中:
父类.func(self) 或 父类.args
# 2
super().func() 或 super().args
用了super()不用传self
继承与派生
派生:子类在父类的基础上又新创建了自己需要的方法和属性
父类有的子类没有 - 子类对象直接调用 就会直接执行父类的方法
父类有的子类也有 - 子类对象调用 直接执行子类中的方法
想在子类中使用父类的名字 : 父类名、super()去调用
规范的编程模式
抽象类 只能被继承 不能被实例化 模板、规则
from abc import ABCMeta,abstractmethod
class A(metaclass=ABCMeta):
@abstractmethod
def func(self):pass
class B(A):
pass
b = B()
b.func()
# 若没有复用A类中的func方法,就会报错
Traceback (most recent call last):
File "E:oldboy_project est.py", line 9, in <module>
b = B()
TypeError: Can't instantiate abstract class B with abstract methods func
多继承
python / c++ 有多继承
java/c# 没有多继承,它们用一个接口类来实现多继承.
语法
每个类中有每个类能完成的方法
创建子类的时候只需要挑选和我相符合的父类来继承就能够完成父类的功能了
接口: java中的一种数据类型
新式类和经典类
新式类中
- 所有的多继承关系寻找方法的顺序 - 遵循广度优先算法
- 默认继承object
- 有mro方法
- 有super方法 : super不是单纯的找父类,而是遵循mro顺序的
经典类
- python2.x
- 不主动继承object
- 经典类在找父类中方法的过程中 遵循 —— 深度优先
- 不提供mro方法和super
多态
不同的子类对象调用相同的 父类方法,产生不同的执行结果
在java中的表现 :
在一个函数中需要给参数指定数据类型,如果这个地方可以接收两个以上类型的参数,那么这些类型应该有一个父类,这个父类是所有子类对象的类型
在python中:
函数的参数不需要指定数据类型,所以我们也不需要通过继承的形式来统一一组类的类型,
换句话说
所有的对象其实都是object类型,所以在python当中其实处处是多态
鸭子类型
不是明确的通过继承实现的多态
而是通过一个模糊的概念来判断这个函数能不能接受这个类型的参数
def len(obj)
len() # str list tuple dict set range(3)
print() # 所有的对象都是鸭子类型
封装
广义上的封装 把属性函数都放到类里
class 类名:
def 方法1(self):pass
是为了只有这个类的对象才能使用定义在类中的方法
狭义上的封装 定义私有成员
把一个名字藏在类中
class Goods:
__discount = 0 # 私有的静态变量
print(__discount)
print(Goods.__discount) # 在类的外部不能引用私有的静态变量
类中的静态变量和方法名在程序加载的过程中就已经执行完了,不需要等待调用
在这个类加载完成之前,Goods这个名字还没有出现在内存空间中
私有的静态属性可以在类的内部使用,用来隐藏某个变量的值
class A:
__count = 0 # 私有的静态变量
print(A.__dict__) # 变形 : _类名__私有变量
print(A._A__count) # 编程规范的角度上出发 我们不能在类的外部使用私有的变量
{'__module__': '__main__', '_A__count': 0, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
0
类中的私有成员:
- 私有的静态属性
- 私有的对象属性
- 私有的方法
为什么要定义一个私有变量
- 不让其他人看到这个值
- 不让其他人修改这个值
- 在修改这个值得时候有一些限制
- 有些方法或者属性不希望被子类继承
私有变量能不能在外部被定义??
class A:
__count = 0
print(__count)
print(A.__dict__)
A.__sum = 10
print(A.__dict__)
0
{'__module__': '__main__', '_A__count': 0, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
{'__module__': '__main__', '_A__count': 0, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, '__sum': 10}
不能,这样只能是添加了一个__sum
的静态属性。而不是私有变量。
私有变量能不能被继承??
不能
class A:
__book = 'python'
def __init__(self, name):
self.__name = name
class B(A):
# print(__book) # NameError: name '_B__book' is not defined
def get_name(self):
return self.__name
b= B('php')
print(b.__dict__) # {'_A__name': 'php'}
面向对象的更多说明
面向对象的软件开发
几个概念的说明
面向对象常用术语