1.定义
函数:
def + 函数名(参数)
面向对象:
class Bar:
def foo(self):
class => 名字为Bar的类
def => 名字为foo的方法
### self必须为类方法的第一个参数,代指调用方法的对象
2.执行
函数:
函数名(参数)
面向对象:
o = Bar() # 创建中间人(对象,实例)
o.foo() # 通过中间人调用方法
class 类名:
def 方法名(self, arg):
print(arg)
# 构造方法
def __init__(self):
特殊作用:
obj = 类名()
# 创建对象
# 通过对象执行类中的一个特殊方法 __init__() 达到初始化效果
class Bar(object): # 创建类Bar
country = '中国' # 静态变量country
def __init__(self, name, age): # 构造方法,初始化
# 普通字段
self.name = name # 实例变量name
self.age = age # 实例变量age
# 普通方法
def foo(self):
print(self, self.name, self.age, self.country)
b = Bar('kay', 30) # 创建实例对象b,并初始化name = 'kay'、age = 30
b.foo() # 调用方法
类成员
字段
普通字段 self.name 普通字段保存在对象中,只能通过对象调用
静态字段 country 保存在类中,可以通过类调用 Bar.country,也可以通过对象调用 self.country
方法
普通方法 def foo(self):pass 保存在类中,通过对象调用 b.foo()
静态方法 @staticmethod 保存在类中,通过类调用 Bar.stat()
def stat(a1, a2):pass
类方法 @classmethod 保存在类中,默认有一个参数cls 通过类调用 Bar.classmd()
# cls 是当前类的类名
def classmd(cls):pass
对普通方法添加装饰器@property时,调用时方法就作为属性调用,不需要加(),对象.方法名
也可以是 变量名 = property(fget=方法名1, fset=方法名2, fdel=方法名3)
应用场景:
如果对象中需要保存一些值,执行某功能时,需要使用对象中的值-->普通方法
不需要使用任何对象中的值时-->静态方法
类继承
class F: # 父类,基类
def foo(self):
pass
class S(F): # 子类,派生类,继承 F
def foo(self): # 重写了父类的方法
super(S, self).foo() # 执行父类中的foo()方法 方法一
F.foo(self) # 执行父类中的foo()方法 方法二
def bar(self):
pass
obj = S()
多继承
class P1(object):
def foo(self):
print 'p1-foo'
class P2(object):
def foo(self):
print 'p2-foo'
def bar(self):
print 'p2-bar'
class C1(P1,P2):
pass
class C2(P1,P2):
def bar(self):
print 'C2-bar'
class D(C1,C2):
pass
1、经典类
实例d调用foo()时,搜索顺序是 D => C1 => P1
实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2
换句话说,经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。
d先查找自身是否有foo方法,没有则查找最近的父类C1里是否有该方法,
如果没有则继续向上查找,直到在P1中找到该方法,查找结束。
2、新式类
使用新式类要继承(object)
实例d调用foo()时,搜索顺序是 D => C1 => C2 => P1
实例d调用bar()时,搜索顺序是 D => C1 => C2
可以看出,新式类的搜索方式是采用“广度优先”的方式去查找属性。
python原生支持多态
面向对象三大特性和五大基本原则
三大特性是:封装,继承,多态
所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,
对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。
简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。
在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。
通过这种方式,对象对内部数据提供了不同级别的保护,
以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。
它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,
并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
继承概念的实现方式有二类:实现继承与接口继承。
实现继承是指直接使用基类的属性和方法而无需额外编码的能力;
接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。
多态机制使具有不同内部结构的对象可以共享相同的外部接口。
这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,
它们(那些操作)可以通过相同的方式予以调用。
五大基本原则
单一职责原则SRP(Single Responsibility Principle)
是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,
否则一天到晚虽然忙忙碌碌的,但效率却高不起来。
开放封闭原则OCP(Open-Close Principle)
一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。
比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,
那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,
这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。
替换原则(the Liskov Substitution Principle LSP)
子类应当可以替换父类并出现在父类能够出现的任何地方。
比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,
也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。
依赖原则(the Dependency Inversion Principle DIP)
具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,
这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,
B只使用这个抽象接口:这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。
通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成循环依赖。
一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。
接口分离原则(the Interface Segregation Principle ISP)
模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来