python之面向对象编程
面向对象三大特性之封装
class Foo:
def __init__(self,host,port,user,pwd):
self.host = host
self.port = port
self.user = user
self.pwd = pwd
def mysql_select(self):
print self.host
def mysql_delet(self):
pass
def mysql_add(self):
pass
def mysql_update(self):
pass
obj1 = Foo('10.10.0.1','3306','root','123') #把参数封装到Foo中self
obj2 = Foo('192.168.1.1','3306','root','456')
obj1.mysql_select()
obj2.mysql_select()
练习二:游戏人生程序
1、创建三个游戏人物,分别是:
- 苍井井,女,18,初始战斗力1000
- 王俊,男,20,初始战斗力1800
- 波多多,女,19,初始战斗力2500
2、游戏场景,分别:
- 草丛战斗,消耗200战斗力
- 自我修炼,增长100战斗力
- 多人游戏,消耗500战斗力
# ##################### 定义实现功能的类 ##################### class Person: def __init__(self,name,sex,age,power): self.name = name self.sex = sex self.age = age self.power = power def grass(self): #草丛作战 self.power = self.power - 200 #草丛战斗,消耗200战斗力 def study(self): #自我修炼 self.power = self.power + 100 #自我修炼,增加100战斗力 def people(self): #多人游戏 self.power = self.power - 500 #参加多人游戏,消耗500战斗力 def detail(self): #人物详情 temp = '姓名:%s;性别%s;年龄%s;战斗力%s'%(self.name,self.sex,self.age,self.power) print temp # ##################### 开始游戏 ##################### cang = Person('苍井井','女',18,1000) #创建苍井井角色 wj = Person('王俊','男',20,1800) #创建王俊角色 bo = Person('波多多','女',19,2500) #创建波多多角色 cang.people() #苍井井参加了一次多人游戏 wj.grass() #王俊参加了一次草丛作战 bo.study() #波多多自我修炼了一次 #输出当前人物详情 cang.detail() wj.detail() bo.detail() cang.grass() #苍井井参加了一次草丛作战 wj.grass() #王俊又参加了一次草丛作战 bo.people() #波多多参加了一次多人游戏 #再次输出当前人物详情 cang.detail() wj.detail() bo.detail()
#!/usr/bin/env python
#codencoding: utf-8
class A:
def a1(self):
print 'a1'
class B(A): #定义B继承A中的方法
def b1(self):
print 'b1'
obj=B() #obj封装到类B
obj.b1()
obj.a1() #继承后,obj才可以调用A中的方法
1、Python的类可以继承多个类,Java和C#中则只能继承一个类
2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
当类是经典类时,多继承情况下,会按照深度优先方式查找
#codencoding: utf-8 class D: def bar(self): print 'D.bar' class C(D): def bar(self): print 'C.bar' class B(D): def bar2(self): print 'B.bar' class A(B, C): def bar1(self): print 'A.bar' a = A()
# 执行bar方法时A --> B --> D --> C
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了a.bar()
当类是新式类时,多继承情况下,会按照广度优先方式查找
#!/usr/bin/env python #codencoding: utf-8 class D(object): def bar(self): print 'D.bar' class C(D): def bar(self): print 'C.bar' class B(D): def bar2(self): print 'B.bar' class A(B, C): def bar1(self): print 'A.bar' a = A()
# 执行bar方法时A --> B --> C --> D
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了a.bar()
#!/usr/bin/env python
#codencoding: utf-8
class Foo:
def __init__(self,name,age):
self.name = name
self.age = age
def fun1(self):
print 'fun1'
@property #将方法fun2转换为字段
def fun2(self):
print 'fun2'
obj = Foo('yangmv',22)
obj.fun1()
obj.fun2 #func被转换为字段,所以可以直接以字段的形式调用
#!/usr/bin/env python:
#codencoding: utf-8
class Foo
country =
'中国' #静态字段。保存在类中(
def __init__
self,name):
self
.name = name
#普通字段。保存在对象中obj_hb = Foo(
'湖北')
print
obj_hb.nameprint
Foo.country
由上图可是:
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
- 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
- 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
- 静态方法:由类调用;无默认参数;
#!/usr/bin/env python面向对象类成员之属性
#codencoding: utf-8
class Foo(object):
def __init__(self):
pass
def f1(self,arg): #普通方法,至少有1个self参数
pass
@classmethod #定义为类方法
def f2(cls): #类方法,参数只能有1个cls
pass
@staticmethod #定义为静态方法
def f3(arg1,arg2): #静态方法,参数任意
pass
obj=Foo()
obj.f1(20) #普通方法调用
Foo.f2() #类方法调用
Foo.f3(11,22) #静态方法调用
由属性的定义和调用要注意一下几点:
- 定义时,在普通方法的基础上添加 @property 装饰器;
- 定义时,属性仅有一个self参数
- 调用时,无需括号
方法:foo_obj.func()
属性:foo_obj.prop
#!/usr/bin/env python:
#codencoding: utf-8
#分页
# ############### 定义 ###############
class Pager
def __init__(
self,index_page):
self
.index_page = index_page
#用户请求的页码.page_itmes =
self
10 #每页默认显示10条数据(
@property #定义为属性
def start
self
):#计算页码从那条数据开始val = (
#1,1 : 第1页从第1条数据开始
#2,11 : 第2页从第11条数据开始
self
.index_page -
1
) *
self
.page_itmes +
1val
return
@property #定义为属性(
def end
self
):#计算页码从那条数据开始val =
#1,10 : 第1页从第10条数据结束
#2,20 : 第2页从第20条数据结束
self
.index_page *
self
.page_itmesreturn
val# ############### 调用 ###############p = Pager(
1
)print
p.start
#p.start()方法加(),属性不用加()
p.end
属性的两种定义方式
属性的定义有两种方式:
- 装饰器 即:在方法上应用装饰器(上面例子)
- 静态字段 即:在类中定义值为property对象的静态字段(下面例子)
#!/usr/bin/env python
#codencoding: utf-8
class Foo:
def fun(self):
return 'yangmv'
BAR = property(fun) #在类中定义值为property对象的静态字段
obj = Foo()
print obj.BAR
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
- 设置私有,字段或方法前加 __
#!/usr/bin/env python
#codencoding: utf-8
class Foo:
__country = 'China' #__设置静态字段为私有
def func(self):
print Foo.__country #私有静态字段在内部可以被调用
#print Foo.country #私有静态字段country在外部无法被调用
obj = Foo()
obj.func()#!/usr/bin/env python
#codencoding: utf-8
class Foo:
def __init__(self):
self.__name = 'yangmv' #普通字段设为私有
def func(self):
print self.__name #内部可以被调用
obj = Foo()
#obj.__name #因此在外部也同样无法被调用
obj.func() #内部调用后输出
设置私有方法
#!/usr/bin/env python
#codencoding: utf-8
#私有普通方法
class Foo:
def __func(self): #设为私有方法
print 'china'
def func2(self):
self.__func() #通过内部调用__func 私有方法
obj = Foo()
#obj.__func #外部无法调用私有方法
obj.func2() #内部调用后输出
#!/usr/bin/env python
#codencoding: utf-8
#私有动态方法
class Foo:
@staticmethod #动态方法
def __func(): #设为私有动态方法
print 'china'
def func2(self):
Foo.__func() #通过内部调用__func 动态私有方法
obj = Foo()
obj.func2() #内部调用后输出
#Foo.__func #外部无法调用私有方法
子类不可以调用父类的私有字段
class Foo:强制访问私有字段或者方法对象._类__成员 obj._Foo__name #强制调用私有字段 Foo._Foo_country
__country = 'China'
class Son:
def func(self):
print Foo.__country
#子类不可以调用父类的私有字段
#强制调用私有方法
面向对象类的特殊成员1. __doc__
表示类的描述信息
2. __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
3. __init__
构造方法,通过类创建对象时,自动触发执行。
4. __del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
5. __call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类
#!/usr/bin/env python
#codencoding: utf-8
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print '__call__'
obj = Foo() # 执行 __init__
obj() # 执行 __call__
6. __dict__
查看对象或类中有什么,并以字典的形式输出
#!/usr/bin/env python
#codencoding: utf-8
class Foo:
def __init__(self):
self.name = 'yangmv'
self.age = '20'
obj=Foo()
print obj.__dict__ #查看对象中
#print Foo.__dict__ #查看类
7. __str__
如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class Foo:
def __str__(self):
return 'yangmv'
obj = Foo()
print obj
# 输出:yangmv。没有__str__的话输出内存地址