您的位置:首页 > 编程语言 > Python开发

[py]戏说python面向对象细节

2018-01-09 22:35 387 查看
面向对象圣经

认识面向对象

什么是面向对象?

有什么实在的好处? 被坑了这么多年,没弄清楚和面向过程有啥切身的区分

我以为这都是大学老师的错. 没把我们启蒙好. 这么多年深受其害. 总结起来三个字: 瞎扯淡. 思想障碍没解决,就懒得理了. 就如同你不信教, 永远也弄不明白那些人那些事及那些仪式有啥实在的价值.





面向对象&面向过程实际区分的直观感受

面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。

while True:
if cpu利用率 > 90%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

if 硬盘使用空间 > 90%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

if 内存占用 > 80%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

随着时间的推移,开始使用了函数式编程,增强代码的重用性和可读性,就变成了这样:

def 发送邮件(内容)
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

while True:

if cpu利用率 > 90%:
发送邮件('CPU报警')

if 硬盘使用空间 > 90%:
发送邮件('硬盘报警')

if 内存占用 > 80%:
发送邮件('内存报警')

面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。

  类就是一个模板,模板里可以包含多个函数,函数里实现一些功能

  对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

面向对象事实上是把描述同一类事物的属性和方法打包成一坨封闭的代码,类似个模子. 当下次描述这个事物时候直接根据模子新建个对象. 是一种编程思想.

而面向过程,一个个的函数是零散的,不能打包用,要一个个调用

代码体现:

函数式:

def kanchai(name, age, gender):
print "%s,%s岁,%s,上山去砍柴" %(name, age, gender)

def qudongbei(name, age, gender):
print "%s,%s岁,%s,开车去东北" %(name, age, gender)

def dabaojian(name, age, gender):
print "%s,%s岁,%s,最爱看书" %(name, age, gender)

kanchai('小明', 10, '男')
qudongbei('小明', 10, '男')
dabaojian('小明', 10, '男')

kanchai('老李', 90, '男')
qudongbei('老李', 90, '男')
dabaojian('老李', 90, '男')

面向对象

class Foo:

def __init__(self, name, age ,gender):
self.name = name
self.age = age
self.gender = gender

def kanchai(self):
print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender)

def qudongbei(self):
print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender)

def dabaojian(self):
print "%s,%s岁,%s,最爱看书" %(self.name, self.age, self.gender)

xiaoming = Foo('小明', 10, '男')
xiaoming.kanchai()
xiaoming.qudongbei()
xiaoming.dabaojian()

laoli = Foo('老李', 90, '男')
laoli.kanchai()
laoli.qudongbei()
laoli.dabaojian()

经常说的面向对象的三个特性

封装 上面阐述过了

继承: 是一种共性的抽取. 把一类事物共同的功能抽取出来.这样子孙的代码就变少了.



最好的栗子是动物吃喝拉撒

class Animal:

def eat(self):
print "%s 吃 " %self.name

def drink(self):
print "%s 喝 " %self.name

def shit(self):
print "%s 拉 " %self.name

def pee(self):
print "%s 撒 " %self.name

class Cat(Animal):

def __init__(self, name):
self.name = name
self.breed = '猫'

def cry(self):
print '喵喵叫'

class Dog(Animal):

def __init__(self, name):
self.name = name
self.breed = '狗'

def cry(self):
print '汪汪叫'

# ######### 执行 #########

c1 = Cat('小白家的小黑猫')
c1.eat()

c2 = Cat('小黑的小白猫')
c2.drink()

d1 = Dog('胖子家的小瘦狗')
d1.eat()

多继承查找顺序: 广度优先



# 查找顺序:A --> B --> C --> D
class D(object):

def bar(self):
print 'D.bar'

class C(D):
def bar(self):
print 'C.bar'

class B(D):
pass

class A(B, C):
pass

a = A()
a.bar()


多态



类和对象在内存中的存储

属性是各自的

方法是共享的



普通字段和静态字段



普通字段属于对象
静态字段属于类

- code
class Province:

# 静态字段
country = '中国'

def __init__(self, name):

# 普通字段
self.name = name

# 直接访问普通字段
obj = Province('河北省')
print obj.name

# 直接访问静态字段
Province.country

- 小结
静态字段在内存中只保存一份
普通字段在每个对象中都要保存一份

在线python内存图

http://www.pythontutor.com/live.html#mode=edit

class Province:
# 静态字段
country = '静态字段: 中国'

def __init__(self, name):
# 普通字段
self.name = name

# 直接访问普通字段
obj = Province('河北省')
print "普通字段: %s"%obj.name

# 直接访问静态字段
Province.country

print "########################################"

# 直接访问普通字段
obj2 = Province('河南省')
print "普通字段: %s"%obj.name
# 直接访问静态字段
Province.country






普通方法/静态方法/类方法

普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
类方法:  由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给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()




相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

不同点:方法调用者不同、调用方法时自动传入的参数不同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: