python基础语法10-面向对象

前面讲到的函数等都是面向过程的编程,今天讲到面向对象的编程。
python从设计开始就已经是一门面向对象的语言,所以说在python中创建一个类和对象是比较容易的。接下来我们就简单介绍一下python的面向对象编程。
一、面向对象的基本概念
面向对象(Object Oriented)是软件开发方法,一种编程范式。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、
应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
面向对象是相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
1.类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
2.方法:类中定义的函数。
3.类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
4.数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
5.方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
6.局部变量:定义在方法中的变量,只作用于当前实例的类。
7.实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
8.继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
9.实例化:创建一个类的实例,类的具体对象。
10.对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
二、类的基本语法规则和使用
1.基本语法规则:
class <类名>:
    类属性1,...,类属性n
    def __init__(self,参数1,...,参数n):#self代表的是类的实例而不是类
        self.实例属性1 = 参数1
        ...
        self.实例属性n = 参数n
    def <方法名1>:
        代码块1
    ...
    def <方法名n>:
        代码块n
实例对象 = 类名(参数1,...,参数n)#实例化创建对象
print(实例对象.类属性1,...,实例对象.类属性n)
print(实例对象.实例属性1,...,实例对象.实例属性n)
实例对象.方法名1()
...
实例对象.方法名n()
(1).关键字class是定义类必须存在的
(2).class 后面的类名用户自己取,通常首字母大写,取名要见名知意
(3).类名后的冒号必不可缺
(4).类的成员有属性和方法组成
(5).类中有个特殊的方法__init__(),它在创建和初始化一个新对象的时候被系统自动调用,初始化方法用于完成对象的初始化工作,如属性的赋值等。
(6).在类中所有方法之外定义的变量是类变量,可以在所有实例之间共享,可以通过类名.类属性和实例对象.类属性名进行访问
(7).对类变量的赋值只能使用类名.类属性进行,不能使用实例对象.实例属性进行
(8).实例变量只能在创建实例对象后通过实例对象.实例属性进行访问
(9).实例变量在定义的时候前面加上了双下划线那就变成了私有变量,只能在该类中使用,出了类就不能直接调用了。
(10).注意如果类属性和实例属性名字相同的情况下,通过实例对象.类属性得到的就是实例属性
示例:
class Person():
    type = '人类'
    def __init__(self,name,high,age):
        self.name = name
        self.high = high
        self.age = age
        self.__hibbit = '画画'
    def eat(self):
        print(self.name+'正在吃饭')
    def sleeps(self):
        print(self.name+'正在睡觉')
    def fun(self):
        print(self.name+'的爱好是'+self.__hibbit)
p = Person('jack',190,20)
print(p.type,p.name,p.high,p.age,Person.type)
print(p.__hibbit)#报错AttributeError: 'Person' object has no attribute '__hibbit'
p.eat()
p.sleeps()
p.fun()
结果如下:
人类 jack 190 20 人类
jack正在吃饭
jack正在睡觉
jack的爱好是画画
2.使用:
类中的方法定义基本与普通定义函数是相同的,只是在类中定义方法分为实例方法、类方法和静态方法
(1)实例方法:在定义的时候传入的第一个参数必须是self,表示当前调用的是这个方法的对象
语法规则:
def <方法名>(self,[参数列表]):
    代码块
在类中调用可以通过self.方法名(参数)进行
在类的外部可以通过实例对象.方法名(参数)进行,只是此时不需要传入参数self的值了
如果在方法名的前面添加双下划线就表示该方法是私有方法,只能在该类中调用,外部无法直接调用。
(2)类方法:在类中定义的方法上方添加@classmethod装饰器,参数的设置中第一个参数不再是self,
而是类对象,参数通常设置为cls,表示当前类,由系统自动传值。
class Car():
    type = '汽车'
    def __init__(self,name,num,speed):
        self.name = name
        self.num = num
        self.speed = speed
    @classmethod
    def run(cls):
        print(self.name)#报错 NameError: name 'self' is not defined
        print(cls.type)
Car.run()
c = Car('公交车','888888',200)
c.run()
类方法只能访问类属性,不能访问实例属性
使用类方法的时候可以用类名.类方法名或者实例对象.类方法名
类方法通常用于定义与该类相关而与具体实例对象无关的操作
(3)静态方法:在类中定义的方法上方添加@staticmethod装饰器,形式上与普通函数并无区别
class Car():
    type = '汽车'
    def __init__(self,name,num,speed):
        self.name = name
        self.num = num
        self.speed = speed
    @staticmethod
    def run():
        print(Car.type)
Car.run()
c = Car('公交车','888888',200)
c.run()
静态方法只能访问属于类的成员,不能访问属于对象的成员
使用静态方法时,可以通过实例对象.静态方法名或者类名.静态方法名
静态方法作为一些工具方法,通常与类和对象都无关
(4)构造方法和初始化方法:
Python的类中有两个特殊的方法:__new__()和 __init__()。这两个方法用于创建并初始化一个对象。
当实例化一个类对象时,最先被调用的是 __new__() 方法。__new__()方法创建完对象后,将该对象传递给
 __init__() 方法中的 self 参数。而__init__()方法是在对象创建完成之后初始化对象状态。这两个
 方法都是在实例化对象时被自动调用的,不需要程序显式调用。__new__() 方法在 object 类中定义,该方法
 至少需要一个参数 cls 表示需要实例化的类。__new__()方法必须要有返回值,返回实例化对象。python中
 的类都直接或间接继承自object类。如果类定义中没有提供 __new__() 方法,将使用从父类继承而来的__new__()
 方法。__init__() 方法有一个参数 self,该参数就是 __new__() 方法返回的实例对象。若__new__() 
 方法没有正确返回当前类 cls 的实例对象,那么__init__()方法将无法被调用。__init__() 方法在 __new__() 
 方法的基础上完成一些初始化工作,不需要返回值。如果用户在类中未提供 __init__() 方法,系统将默认调用父类的初始化方法。
import time
class Student():
    def __init__(self,name):
        self.name = name
        init_time = time.strftime("%Y-%m-%d %H:%M:%S")
        print(init_time)
    def set_major(self,major):
        self.major = major
s = Student('jack')#创建对象
print(dir(s))
s.set_major('计算机')#调用方法
print(dir(s))
s.num = '007'#新增的示例属性
print(dir(s))
print(s.sex)#访问不存在的实例属性报错
三、类的继承
Python同样支持类的继承,如果一种语言不支持继承,实现功能的代码块就没法进行复用,这样的话类就没有什么意义。
继承是指创建一个类的时候,并不是重零开始构建,而是在已经存在的类的基础上进行扩展,能够有效的降低工作量。
语法规则:
class DerivedClassName(Base1, modname.Base, ..., Base3):
示例1:
#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        # people.__init__(self,n,a,w)
        super().__init__(n,a,w)
        self.grade = g
    #重写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
#另一个类,多重继承之前的准备
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中参数位置排前父类的方法
示例2:
class Parent:        # 定义父类
   def myMethod(self):
      print ('调用父类方法')
class Child(Parent): # 定义子类
   def myMethod(self):
      print ('调用子类方法')
c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
注意:
新建的一个类可以继承一个或多个父类,父类又称为基类或者超类,新建的类称为派生类或者子类。
定义类的时候如果没有指定父类,默认父类为object,object类是指所有类的直接父类或者间接祖先类。
子类可继承父类的公有成员,但不能继承其私有成员,如果需要在子类中调用父类的方法,可以使用super().方法名()或者基类名.方法名()。
类继承的时候注意圆括号中父类的顺序,使用类的实例对象调用一个方法时,若在子类中未找到,则会从左到右查找父类中是否包含该方法。
当没有指定父类时,可以省略一对圆括号。通过类提供的__bases__ 属性可以查看该类的所有直接父类。
当父类的方法不能满足子类的要求时,可以在子类中重写父类的方法,也就是在子类中写一个和父类的方法名相同的方法。
四、类的专有方法
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__truediv__: 除运算
__mod__: 求余运算
__pow__: 乘方
五、总结
面向过程的优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
面向过程的缺点:不易维护、复用和拓展
面向对象的优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
面向对象的缺点:性能比面向过程低
高内聚、低耦合:
内聚:模块内部的代码,例如方法,变量,对象,或者是功能模块。相互之间的联系越强,内聚就越高,模块的独立性就越好。一个模块应该尽量的独立,去完成独立的功能
耦合:模块与模块之间有些操作是有关联的,例如水桶效应,一个水桶若是有一块木板比其他木板短,那么这个水桶装的水也就会相应减少,因此模块与模块之间的关系越是紧密,独立性就越不好,就容易产生连锁反应
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春风抚微霞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值