Python面向对象讲解

一、面向过程和面向对象(oop:object oriented programming)区别

面向过程--->侧重于怎么做?
面向对象--->测中于谁来做?

面向过程:—侧重于怎么做?

1.把完成某一个需求的 所有步骤 从头到尾 逐步实现
2.根据开发要求,将某些功能独立的代码封装成一个又一个函数
3.最后完成的代码,就是顺序的调用不同的函数

特点

1.注重步骤和过程,不注重职责分工
2.如果需求复杂,代码变得非常复杂
3.开发复杂的项目的时候,没有固定的套路,开发难度很大

面向对象:----侧重于谁来做?
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法

1.在完成某一个需求前,首先确定职责--要做的事(方法)
2.根据职责确定不同的对象,在对象内部封装不同的方法(多个)
3.最后完成代码,就是顺序的让不同的对象调用不同的方法

二、python面向对象的理解
1、特点:

1.注重对象和职责,不同的对象承担不同的职责
2.更加适合对复杂的需求变化,是专门应对复杂项目的开发,提供固定的套路
3.需要在面向过程的基础上,再学习一些面向对象的语法

2、python面向对象的重要术语:

   1、多态(polymorphism):一个函数有多种表现形式,调用一个方法有多种形式,但是表现出的方法是不一样的。
  2、继承(inheritance)子项继承父项的某些功能,在程序中表现某种联系
  3、封装(encapsulation)把需要重用的函数或者功能封装,方便其他程序直接调用
  4、类:对具有相同数据或者方法的一组对象的集合
  5、对象:对象是一个类的具体事例
  6、实例化:是一个对象实例化的实现
  7、标识:每个对象的实例都需要一个可以唯一标识这个实例的标记
  8、实例属性:一个对象就是一组属性的集合
  9、事例方法:所有存取或者更新对象某个实例一条或者多条属性函数的集合。
  10、类属性:属于一个类中所有对象的属性,
  11、类方法:那些无须特定的对象实例就能够工作的从属于类的函数。

3、面向对象有两个核心的概念:

类:是一类具有相同特征或行为的事物的一个统称
对象:由类创建出来的一个具体的存在

4、类和对象的关系:

先有类再有对象
类是模板 对象是根据这个模板创建出来的
类只需要有一个 对象可以有多个


由属性(这一类事务的共同信息) 和 方法(你能完成的动作)组成

1.类名:这类事物的名字(大驼峰命名法)
    大驼峰命名法:
        1.每个单词的首字母大写
        2.单词与单词之间没有下划线
2.属性:这个类创建出来的对象有什么特征
3.方法:这个类创建出来的对象有什么行为

类名的确定
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类

属性和方法的确定
对 对象的特征描述,通常可以定义成属性
对象具有的行为(动词),通常可以定义为方法
提示:需求中没有涉及的属性或方法在设计类时,不需要考虑
5、函数和面向对象编程的区别
  相同点:都是把程序进行封装、方便重复利用,提高效率。
  不同点:函数重点是用于整体调用,一般用于一段不可更改的程序。仅仅是解决代码重用性的问题。
  而面向对象除了代码重用性。还包括继承、多态等。使用上更加灵活。
三、函数方法

__ init __方法:

初始化方法,是专门用来定义一个类据有哪些属性和方法的
创建对象的时候,python解释器会自动执行以下操作
1.为对象在内存中分配空间–创建对象
2.调用初始化方法为对象的属性设置初始值
实例
在这里插入图片描述
结果
在这里插入图片描述

__ str __方法:

在python中 使用print输出对象变量时候,默认情况下
会输出这个变量引用的对象是由哪一个类创建的对象以及在内存中的地址
如果在开发中,希望使用print输出变量的时候,能够打印自定义内容,就可以利用__str__这个内置的方法了
实例
在这里插入图片描述
结果
在这里插入图片描述

__ del __方法:

如果希望在对象被销毁之前,再做一些事情,可以考虑一下__del__
当一个对象被从内存中销毁前(把这个对象从内存中删除掉),
会自动调用 __del__方法
实例
在这里插入图片描述
结果
在这里插入图片描述
__new__方法:
用 类名 的方式创建对象的时候,python解释器会帮我们做两件事情,是哪两件事情呢?

为对象分配空间
对象初始化

使用类名()创建对象时,python的解释器首先会调用__new__方法为对象分配空间
__new__是一个由object基类提供的内置的静态方法,主要有两个作用:

在内存中为对象分配空间
返回对象的引用

python的解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法
new:负责给对象分配空间
init(初始化方法)负责给对象初始化

我们要重写new方法,使用类名()创建对象的时候,返回的都是同一个地址
重写__new__方法的代码非常固定:

继承自父类方法
返回父类方法调用_new__方法的结果

重写__new__方法一定要return object.__ new __(cls)
否则python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
实例
模拟音乐播放器,一次只能播放一首歌曲
实现:
重写new方法,使用类名()创建对象的时候,返回的都是同一个地址
在这里插入图片描述
结果
在这里插入图片描述注意:
前面带两个下划线表示对变量进行私有化
外部不能随便访问和更改
错误实例:
在这里插入图片描述在这里插入图片描述在这里插入图片描述结果:在这里插入图片描述
正确实例:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

结果:
在这里插入图片描述
四、封装、继承、多态

1、封装(Encapsulation)

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

  class Foo:
     
        def __init__(self, name, age ,gender):
            self.name = name
            self.age = age
            self.gender = gender
     
        def eat(self):
            print "%s,%s岁,%s,吃饭" %(self.name, self.age, self.gender)
     
        def he(self):
            print "%s,%s岁,%s,喝水" %(self.name, self.age, self.gender)
     
        def shui(self):
            print "%s,%s岁,%s,睡觉" %(self.name, self.age, self.gender)
     
    a = Foo('jack', 10, '男')
    a.eat()
    a.he()
    a.shui()
     
    b = Foo('rose', 11, '女')
    b.eat()
    b.he()
    b.shui()

2、继承(Inheritance)

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

例如:

猫可以:喵喵叫、吃、喝、拉、撒

狗可以:汪汪叫、吃、喝、拉、撒

公共的部分就是 吃、喝、拉、撒

如下实现:

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('猫one')
c1.eat()
 
c2 = Cat('猫two')
c2.drink()
 
d1 = Dog('狗one')
d1.eat()

注意: 关于多继承

  • 在Python中,如果父类和子类都重新定义了构造方法init( ),在进行子类实例化的时候,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用。
  • Python的类可以继承多个类,Java和C#中则只能继承一个类
  • Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
  • 当类是经典类时,多继承情况下,会按照深度优先方式查找,当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了更多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
新式类和旧式(经典)类:
object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看

新式类:以object为基类的类
经典类 不以object为基类的类

在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类–
python3.x中定义的类都是新式类
在这里插入图片描述
在python2.x中定义类时,如果没有指定父类,则不会以object作为基类在这里插入图片描述

为保证编写的代码能够同时在python2.x和python3.x运行
今后在定义类时,如果没有父类,建议统一继承自object
3、多态(Polymorphism)

首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

例子:

class A:     #定义类
    def prt(self):    #定义方法
        print "A"    
 
class B(A):    
    def prt(self):    
        print "B"    
 
class C(A):    
    def prt(self):    
        print "C"    
 
class D(A):    
    pass    
 
class E:    
    def prt(self):    
        print "E"    
 
class F:     
    pass    
 
def test(arg):    
    arg.prt()    #执行arg对象的prt方法
 
a = A()    #定义对象
b = B()    
c = C()    
d = D()    
e = E()    
f = F()    
 
test(a)    #将对象作为参数传给函数test
test(b)    
test(c)    
test(d)    
test(e)    
test(f) 
 
# 结果
A  
B  
C  
A  
E  

没有谁规定test方法是接收的参数是什么类型的。test方法只规定,接收一个参数,调用这个参数的prt方法。在运行的时候如果这个参数有prt方法,python就执行,如果没有,python就报错,因为abcde都有prt方法,而f没有,所以得到了上边得结果,这就是python的运行方式。
五、面向对象的各种方法
1、静态方法 (用这个装饰器来表示 @staticmethod )

意思是把 @staticmethod 下面的函数和所属的类截断了,这个函数就不属于这个类了,没有类的属性了,只不是还是要通过类名的方式调用

看个小例子:

错误示例:
 
class Person(object):
    def __init__(self, name):
        self.name = name
 
    @staticmethod  # 把eat方法变为静态方法
    def eat(self):
        print("%s is eating" % self.name)
 
 
d = Person("xiaoming")
d.eat()  
 
############## 
 
结果:
TypeError: eat() missing 1 required positional argument: 'self'

因为用静态方法把eat这个方法与Person这个类截断了,eat方法就没有了类的属性了,所以获取不到self.name这个变量。

正确示例: 
 
 
class Person(object):
    def __init__(self, name):
        self.name = name
 
    @staticmethod  # 把eat方法变为静态方法
    def eat(x):
        print("%s is eating" % x)
 
 
d = Person("xiaoming")
d.eat("jack")   

就把eat方法当作一个独立的函数给他传参就行了

2、类方法 (用这个装饰器来表示 @classmethod)
@classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法。 类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例。
类方法只能访问类变量,不能访问实例变量
使用@staticmethod或@classmethod,可以不需要实例化,直接类名.方法名()来调用。
@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等

看个例子:

 错误示例: 
     
    class Person(object):
        def __init__(self, name):
            self.name = name
     
        @classmethod  # 把eat方法变为类方法
        def eat(cls):
            print("%s is eating" % cls.name)
     
    d = Person("xiaoming")
    d.eat()  
     
    ###########   
     
    结果: 
    AttributeError: type object 'Person' has no attribute 'name'

因为self.name这个变量是实例化这个类传进去的,类方法是不能访问实例变量的,只能访问类里面定义的变量

class Person(object):
    name="杰克"
    def __init__(self, name):
        self.name = name
 
    @classmethod  # 把eat方法变为类方法
    def eat(cls):
        print("%s is eating" % 	cls.name)   
 
d = Person("xiaoming")
d.eat()

3、属性方法 (用这个装饰器表示 @property)

把一个方法变成一个静态属性,属性就不用加小括号那样的去调用了

看个小例子:

  错误示例: 
     
    class Person(object):
     
        def __init__(self, name):
            self.name = name
     
        @property  # 把eat方法变为属性方法
        def eat(self):
            print("%s is eating" % self.name)
     
     
    d = Person("xiaoming")
    d.eat()  
     
     
    ########## 
    结果: 
    TypeError: 'NoneType' object is not callable

因为eat此时已经变成一个属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了

class Person(object):
 
    def __init__(self, name):
        self.name = name
 
    @property  # 把eat方法变为属性方法
    def eat(self):
        print("%s is eating" % self.name)
 
 
d = Person("xiaoming")
d.eat
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值