Python--面向对象初体验

面向过程

面向过程:核心是过程二字,过程即解决问题的步骤
基于该思想写程序就类似流水线
优点:复杂的过程简单化
缺点:扩展性差

面向对象

面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。

优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。

缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。面向对象的程序设计好比如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题需要四个人:唐僧,沙和尚,猪八戒,孙悟空,每个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的属性和方法),然而这并不好玩,于是如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。然后取经开始,师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。

面向对象的程序设计的

优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。

应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。

在python 中面向对象的程序设计并不是全部。

面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

了解一些名词:类、对象、实例、实例化

类:具有相同特征的一类事物(人、狗、老虎)

对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)

实例化:类——>对象的过程(这在生活中表现的不明显,我们在后面再慢慢解释)

面向对象特点

将某些相关的功能(函数)封装在一起;
上帝的角度创建了一个模板,通过模板创建不同的对象;
在现实世界:一定先有一个个具体存在的对象,后总结出的类
计算机世界:一定保证先定义类后产生对象
#class demo
class Person: 
    animal = "高级动物" #静态属性
    def __init__(self,name,age,sex): #对象属性
        self.name = name
        self.age = age
        self.sex = sex
    
    #类的方法
    def work(self):     
        print("%s会工作,今年%s岁他是一个%s人" %(self.name,self.age,self.sex))
    
p1 = Person("jim",28,"男")  #创建对象

#结构分析:类一般分为两部分:变量 方法
#思想分析:创建一个类:创建一个公共模板通过创建个体对象可以享有公共方
我们通过上面的栗子了解了类与对象的基本定义,那么我们来分解一下上面的代码
1.我们有一个test类,定义了一个静态属性和动态方法
2.我们实例化了一个对象p1然后传递了3个参数

我们发现无论是__init__方法还是普通的动态方法都包含一个self,那这个self又是什么呢?
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做

我们定义的类的属性到底存到哪里了?有两种方式查看
1.dir(类名):查出的是一个名字列表
2.类名.__dict__:查出的是一个字典,key为属性名,value为属性值

特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

我们了解了类和对象的基本概念也知道怎么定义一个类和对象,那么接下来我们来介绍一下通过类名我们能干哪些事情吧;
类名调用静态属性
class pay:
"""
这是一个支付类
"""
    name = "支付接口"

    def pay_port(self):
    print("我是一个支付接口")

    def red_packet(self):
    print("我是发红包功能")

print(pay.__dict__)    #查看类的名称空间
#查看属性
print(pay.name)       #pay.name:类的静态属性

#增加属性
pay.country = "China"
print(pay.country)

#修改
pay.country = "china"
print(pay.country)

#删除
del pay.country
print(pay.country)
类名调用动态方法
#一般不建议使用类名调用类的动态方法,除类方法与静态方法
class pay:
"""
这是一个支付类
"""
     name = "支付接口"

     def pay_port(self):
         print("我是一个支付接口")


     def red_packet(self):
        print("我是发红包功能")
        
print(pay.pay_port) #调用类的动态方法

对象

我们也了解了通过类名可以做哪些事情,那么来聊聊对象的那些事情,这里的对象不是女朋友而是类的实例化,我们要时时刻刻记住这个概念:对象 = 类名():一个类实例化对象的过程
那么我们来聊聊实例化对象的到底都干了啥;
1.对象 = 类名()调用object类的__new__方法创建一个对象
2.对象在内存开辟一个对象地址空间;
3.对象内存空间里有一个叫“类内存指针”对象通过它就能知道自己是哪个类的实例化也就自动去加载类的__init__这个特殊的方法
4.自动执行类__init__这个特殊方法,自动将对象地址空间传递给__init__方法的self参数;
5.在__init__方法中给对象地址空间封装一些静态属性
class test:
    name = "火影忍者"    #类的静态属性
    def __init__(self,name,age,ad,hp):  #__init__:对象的特殊方法(用于给对象封装静态属性):(self:对象空间的内存地址,name,age,ad,hp:对象的静态属性)
        self.name = name   #self.name = name:对象地址空间里定义一个叫name的变量接收__init__方法传递的第一个位置参数:name
        self.age = age #同上
        self.ad = ad   #同上
        self.hp = hp   #同上
    def test(self):    #类的动态方法:self = 对象的内存地址空间;
        pass

you = test("宇智波鼬","男",10000,500)
print(you.name)
我们了解对象的定义和怎么产生的对象,那么介绍一下对象能做哪些事情吧;
对象调用类的静态属性
#格式:对象.类的静态属性
class test:
    state = "木叶"   
    def __init__(self,name,age,ad,hp): 
        self.age = age
        self.ad = ad
        self.hp = hp
    def test(self):
        pass
you = test("宇智波鼬","男",10000,500)
print(you.state)   #对象在自己的地址空间找不到就会去类查找
print(test.state)  #直接调用类静态属性
对象调用类的动态方法
对象.类的动态方法
class test:
    name = "火影忍者"    #类的静态属性
    def __init__(self,name,age,ad,hp):  
        self.age = age
        self.ad = ad
        self.hp = hp
    def test(self,*args,**kwargs):
        print("我是一个动态属性")
        print(args)
        return 1
you = test("宇智波鼬","男",10000,500)
print(you.test(1,2,3,4))
对象查看自己空间的属性
我们了解了对象的一些功能,那么我们怎么查看对象自己的属性呢?
class test:
    state = "中国"
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def test(self):
        print("我是{},今年{}" .format(self.name,self.age))

a = test("jim",28,"Man")
print(a.__dict__)   #查看对象属性
print(a.state)
a.test()
通过上面的代码我们发现一个问题,我们可以通过对象查看一个不在类空间的静态属性state,那么介绍一下对象查找属性的顺序
1.对象本身名称空间
2.类的名称空间
3.父类名称空间
我们来总结一下:
1.类中定义的方法是绑定给对象使用的
2.不同的对象就是不同的绑定方法
3.绑定给谁就应该由谁调用,谁来调用就会把对象的内存地址传递给类方法里的self参数
4.对象与对象之间不能互相访问
5.类所有属性共享,所有对象内部都包含一个"类内存指针":指向这个对象属于哪个类

类即类型

#在python中接触到的数据类型 如列表 字典 字符串等其实都是一个类
a = "test"
b = 1
c = []
d = {}
e = ()
print(type(e))

#我们拿列表举例在列表中c = [] 其实就是list这个类的对象叫c
#我们通过c.append()可以追加元素其实就是调用list类里的append()方法将元素追加到a这个对象的内存空间

面向对象--组合

组合:对象中的属性是另一个类的对象
组合的作用:让类的对象与另一个类的对象发生关联从而互相访问
#基础代码
class test:
    """
    模拟攻击
    """
    name = "火影忍者"
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def fight(self,role1):
        role1.hp = role1.hp - self.ad
        print("%s攻击了%s,%s掉了%s" %(self.name,role1.name,role1.name,role1.hp))

test1 = test("鸣人",10000,8000)
test2 = test("佐助",10000,6000)

test1.fight(test2)
#类的组合
class test:
    """
    模拟攻击
    """
    name = "火影忍者"

    def __init__(self, name, ad, hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def eqit_weapon(self,wea):
        self.wea = wea

class weapon:
    """
    技能库
    """
    def __init__(self, name, ad):
        self.name = name
        self.ad = ad

    def weapon_attack(self,role1,role2):
        role2.hp = role2.hp - self.ad
        print("%s使用了%s攻击了%s,%s剩余%s" %(role1.name,self.name,role2.name,role2.name,role2.hp))


test1 = test("鸣人", 10000, 8000)
test2 = test("佐助", 10000, 6000)
test3 = weapon("螺旋丸",100)
test4 = weapon("千鸟",70)
test1.eqit_weapon(test3)
test2.eqit_weapon(test4)
test1.wea.weapon_attack(test1,test2)
test2.wea.weapon_attack(test2,test1)

#我们来分析一下上面都做了哪些事情
#1.test这个类实例化了test1 test2;weapon类实例化了test3 test4
#2.在内存中开辟了4个对象地址空间存放了自己的属性
#3.test1.eqit_weapon(test3):test1对象发现自己的对象空间没有eqit_weapon()方法就
#通过类内存指针找到了自己的类调用了eqit_weapon()方法并将test3的内存地址传递进去
#4.test1在自己的内存空间新建了一个静态属性:wea对应的值是test3的内存地址空间
#5.test2同理
#6.test1这个对象调用自己的内存空间里的wea属性然后指向到了test3的地址空间
#7.在test3的地址空间里通过类内存指针找到了weapon_attack()方法并将test1和test2传递进去
#8.由于调用weapon_attack()方法的属于test3所以self.name是test3内存空间里的name并不是test1里的name

猜你喜欢

转载自www.cnblogs.com/olingrobin/p/10174459.html