概述
关于python的编程有以下几种方式
- 面向过程:根据业务逻辑从上到下写垒代码
- 函数式: 将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象: 对函数进行分类和封装,让开发“更快更好更强”
创建类和对象
面向对象其实就是对类和对象的使用,类就是一个模版,模版里包含多个函数,函数里实现一些功能;对象则是根据模版创建实例,通过实例对象可以执行类中的函数。
class Foo:
#创建类中的函数
def Bar(self):
#do something
#根据类Foo创建对象obj
obj = Foo()
python 自醒反射继承鸭子类型类方法静态方法静态字段属性装饰器
面向对象的三大特性
封装
封装故名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
class Foo:
def __init__(self,name,age):
self.name = name
self.age = age
#根据类Foo创建对象
#创建对象时,会自动执行类的__init__方法
obj1 = Foo('kaiz',18)
obj2 = Foo('amm',28)
#如上,即是将kaiz,18分别封装到obj1/self的name和age属性中
#self是一个形式参数,当执行obj1 = Foo('kaiz',18)时,self等于obj1
调用被封装的内容
- 通过对象直接调用
class Foo:
def __init__(slef,name,age):
self.name = name
self.age = age
obj1 =Foo('kaiz',18)
print obj1.name
print obj1.age
- 通过self间接调用
class Foo:
def __init__(slef,name,age):
self.name = name
self.age = age
def detail(self):
print self.name
print self.age
继承
继承,子类继承父类(派生类继承基类)
class Father:
def __init__(self,name,age):
self.name = name
self.age = age
def bad_hobby:
print "smoke,drink"
class Son(Father):
def __init__(self,name,age):
self.name = name
self.age = age
#创建Son类的对象
obj = Son('amm',18)
#由于是继承,因此obj具由Father类的方法
obj.bad_hobby
> smoke,drink
同时继承后,子类可以改良父类的方法。另:类分经典类和新式类,如果父类继承了object类,那么该类就是新式类,否则便是经典类。在多继承中,当类是经典类时,会按照深度优先方式查找;当类是新式类时,会按照广度优先试查找。
#多继承
class A(B,C)
多态
class F1:
pass
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
def Func(obj):
print obj.show()
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
类的成员
类的成员可以分为三大类:
- 字段:普通字段、静态字段
- 方法:普通方法、类方法、静态方法
- 属性: 普通属性
字段
普通字段和静态字段在定义和使用中有所区别,本质区别是内存中保存位置不同;普通字段属于类对象,静态字段属于类
class Province:
#静态字段
country = '中国'
def __ini__(self,name):
#普通字段
self.name = name
#直接访问普通字段
obj = Province('河北省')
print obj.name
#直接访问静态字段
Provice.country
由上述代码可以看出普通字段需要创建对象来访问,静态字段通过类来访问。
方法
- 普通方法:由对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self
- 类方法:由类调用,至少一个cls参数,执行类方法时,自动将调用该方法的类复制给cls 被classmethod修饰的函数不需要实例化就可以直接调用,不需要self参数,传入cls参数
- 静态方法:由类调用,无默认参数
class Foo:
def __init__(self,name):
self.name = name
def ord_func(self):
"""定义普通方法,至少一个self参数"""
#print self.name
print 普通方法
@classmethod
def class_func(cls):
"""定义类方法,至少有一个cls参数"""
print "类方法"
@staticmethod
def static_func():
"""定义静态方法,无默认参数"""
print '静态方法'
#调用普通方法
f = Foo()
f.ord_func()
#调用类方法
Foo.class_func()
#调用静态方法
Foo.static_func()
补充一个类方法的示例
In [9]: class A:
...: def __init__(self):
...: self.name="zk"
...: def get_name(self):
...: print(self.name)
...: @classmethod
...: def get_name_cls(cls):
...: cls().get_name()
In [10]: A.get_name_cls()
zk
In [24]: class foo(object):
...: price = 5
...: def __init__(self,name):
...: self.name = name
...: def regular_func(self):
...: print(self.name)
...: @staticmethod
...: def static_method_func():
...: print("static_method_func")
...: @classmethod
...: def classmethod_func(cls,name):
...: cls(name).regular_func()
In [26]: A=foo("kaiz")
In [27]: A.regular_func()
kaiz
In [28]: A.price
Out[28]: 5
In [29]: A.static_method_func()
static_method_func
In [30]: A.classmethod_func("amm")
amm
属性
属性就是普通方法的变种,在定义时,在普通方法的基础上添加@property装饰器,属性仅有一个self参数,调用时无需括号;方法: foo_obj.func(),属性: foo_obj.prop; 属性两种定义方式,一种是用装饰器的形式,一种是静态字段
- 属性的基本使用
###########定义#########
class Foo:
def Func(self):
pass
#定义属性
@property
def prop(self):
return "kaiz"
pass
###########调用##########
foo_obj = Foo()
foo_obj.func()
foo_obj.prop
#调用属性
result = foo_obj.prop
类成员的修饰符
类成员的修饰符
- 私有成员:私有成员在命名时,前两个字符是下划线,特殊成员除外如: _init_、_call_、__dict__等
class C:
def __init__(self):
self.name = '公有字段'
self.__foo = '私有字段'
- 公有成员:公有静态字段类可可以访问,类内部也可以访问,派生类中也可以访问;私有静态字段,仅类内部可以访问
class C:
name = '公有静态字段'
def func(self):
print C.name
class D(C):
def show(self):
print C.name
C.name #类访问
obj = C()
obj.func() #类内部可以访问
obj_son = D()
obj_son.show() #派生类中可以访问
对照如下
class C:
__name = "公有静态字段"
def func(self):
print C.__name
class D:
def show(self):
print C.__name
C.__name #类访问 --> 错误
obj = C()
obj.func() #类内部可以访问 -->正确
obj_son = D()
obj_son.show() #派生类中可以访问 -->错误
类的特殊成员
__doc__
表示类的描述信息
class Foo:
"""描述类信息"""
def func(self):
pass
print Foo.__doc
#输入类的描述信息
- _module_:表示当前操作的对象在哪个模块
- __class__表示操作的对象的类是什么
- _init_
- _del_:析构方法,对对象在内存在被释放时,自动触发执行,最后一次呐喊。注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo:
def __del__(self):
pass
- _call_:对象后面加括号触发执行
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print '__call__'
obj = Foo() # 执行 __init__
obj() # 执行 __call__
- _dict_:类或对象中的所有成员
- _str_:如果一个类中定义了__str__方法,那就在打印对象时,默认输入该方法的返回值。如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
def __str__(self): return 'kaiz' obj = Foo() print obj # 输出:kaiz
- _getitem_、_setitem_、_delitem_:用于索引操作,如字典。以上分别表示获取、设置、删除数据
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
def __getitem__(self, key):
print '__getitem__',key
def __setitem__(self, key, value):
print '__setitem__',key,value
def __delitem__(self, key):
print '__delitem__',key
obj = Foo()
result = obj['k1'] # 自动触发执行 __getitem__
obj['k2'] = 'wupeiqi' # 自动触发执行 __setitem__
del obj['k1'] # 自动触发执行 __delitem__
- _getslice_、_setslice_、_delslice_
该三个方法用于分片操作,如列表:
#!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __getslice__(self, i, j): print '__getslice__',i,j def __setslice__(self, i, j, sequence): print '__setslice__',i,j def __delslice__(self, i, j): print '__delslice__',i,j obj = Foo() obj[-1:1] # 自动触发执行 __getslice__ obj[0:1] = [11,22,33,44] # 自动触发执行 __setslice__ del obj[0:2] # 自动触发执行 __delslice__
- _iter_ 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 _iter_
eg:
class foo(object):
def __init__(self,name):
self.name=name
def __call__(self):
print("this is call function")
def __del__(self):
print("this is del function")
def __str__(self):
return "amm"
In [22]: A=foo("kaiz")
In [24]: A.__dict__
Out[24]: {'name': 'kaiz'}
In [25]: A='asdf'
this is del function
装饰器
对函数进行封装,直接上代码
import time
def timeit(f):
def timer(*arg):
start = time.time()
result = f(*arg)
end = time.time()
print("Function runtime is %s" % (end-start))
return result #记住此处处最好有个返回值
return timer
@timeit
def factorial_two(n):
if n == 1:
return 1
elif n > 1:
return n * factorial_two(n-1)
else:
return 0
print(factorial_two(4))
Function runtime is 0.0
Function runtime is 0.0
Function runtime is 0.0
Function runtime is 0.0
24