8 类和对象

类和对象

1 面向对象的思想

面向过程:面向处理,更多的是从计算机角度思考,注重计算每一个步骤,程序更像是一本cpu操作手册。

面向对象:以日常生活的角度思考问题的解决,更接近人的思维方式,让人可以从更高的层面考虑系统的构建

以你请朋友吃饭为例:

面向过程面向对象
自己买菜和朋友一块到饭店
自己摘菜叫服务员点菜
自己洗菜和朋友一块吃
自己做菜
和朋友一块吃

面向对象的优点:

  • 面向对象更加适合做应用的开发
  • 面向对象可以使你的代码更加优雅和紧凑
  • 面向对象开发效率更高
  • 面向对象代码复用度更高、可维护性更好

面向对象是一种思维方式,它认为万事万物皆对象,程序是由多个对象协作共同完成功能的,所以以后我们要从面向过程转向面向对象。以面向对象的方式考虑程序的构建。面向对象的核心是:类和对象

问题->面向对象分析(OOA)->发现对象->类->用类实例化对象->对象协作完成功能

2. 类和对象

2.1 类和对象的概念

生活角度

  • 类:具有相同特征和行为的对象的集合,是一个概念
  • 对象:客观存在的一切事物,是类的实例

​ 类: 汽车 超级英雄 电脑 杯子

​ 对象: 红色的宝马 美国队长 桌上的mac pro 老王的黑色杯子

程序角度

  • 类:用户自定义的数据类型,是模板,不占用内存
  • 对象:由类定义的变量,占用内存
类:
  成员属性(成员变量)  描述对象的静态特征,诸如,名字、身高体重
  成员方法  描述对象的动态特征,例如:吃饭、睡觉、打豆豆

2.2 类的定义

#语法:
class  类名:
     类体

注意:

  • 类定义必须以关键字class
  • 类名要符合标识符的规范
  • 类名一般用大驼峰风格: 每个单词首字母大写,其它小写 ,例如MyBook YouMoney
  • 类体必须缩进
  • 在python3中类默认继承object,所以可以这样写 class Dog:,它等价于class Dog(object):
  • 一个文件里只放一个类

2.3 成员方法

成员方法其实就是函数,作用域在类内,成员方法的第一个参数必须是self,self代表当前对象,也就是调用这个方法的对象,这个参数由系统传递。

class Dog(object):
    def bark(self):  #成员方法,第一个参数必须是self,代表当前调用对象
        print('我是小可爱--丁丁')

dingding = Dog()  #实例化一个对象

#调用方法,不需要传参数,self是系统传递的
#调用形式: 对象.方法([实参])
dingding.bark()   #等价调用形式:bark(dingding)

注意:

  • self参数在调用的时候不必传值,由系统传值
  • self只能在实例方法中使用
  • 方法和函数的区别:
    • 方法作用域属于类,所以即便和普通函数重名,也不会被覆盖
    • 方法的第一个参数必须是self,但函数不要求
    • 方法必须通过对象调用,而函数不需要
  • 方法的第一个参数self其实可以使任何合法标识符,不过一般约定俗成都是self
  • 方法的连贯调用
class Dog:
    def bark(self):
        print("汪汪汪")
        return self   #返回self
    def eat(self):
        print("爱啃大骨头")
        return self
dog = Dog()
dog.eat().bark()  #方法的连贯调用

2.4 对象的创建

对象的创建过程也称之为对象的实例化过程,也就是定义了一个类类型的变量或者称之为实例(instance)的过程

#语法:  对象  = 类名([实参])
dingding = Dog()  #实例化一个对象
print(dingding)   #<__main__.Dog object at 0x00000000023F40B8>
print(type(dingding)) #<class '__main__.Dog'>

#查看对象的类名
print(dingding.__class__)

2.5 成员属性

成员属性描述的是对象的静态特征,比如说狗名字、品种等,其实就是一个变量,作用域属于类,不会和类外的全局变量冲突。python中成员属性可以在构造函数中添加。成员属性属于对象,每个对象的成员属性的值都不同

  • 在构造函数中添加的属性属于所有对象(重点)
#添加属性语法:
   对象.成员属性  =#引用方式:对象.成员属性

class Dog(object):
    def __init__(self,name,kind,age):
        self.name = name
        self.kind = kind
        self.age = age
    def bark(tmp):
        print('我是小可爱--丁丁')

dingding = Dog('丁丁','泰迪',3)
print('我是可爱的%s犬,%s,我今年%d岁了' % (dingding.kind, dingding.name, dingding.age))

#查看实例属性
print(dingding.__dict__)  #__dict__属性可以用来查看实例属性
print(dir(dingding))  #查看Dog的属性,包括实例属性

3.封装

​ 隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读取和修改的访问级别。

​ 类本身就是一种封装,通过类可以将数据(属性)和行为(方法)相结合,形成一个有机的整体,也就是将数据与对数据的操作有机的结合。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。成员私有化是实现封装的手段。所有的成员默认是公有。

3.1 属性私有化

​ 如果想让类的内部属性不被外界直接访问,可以在这个属性的前面加两个下划线__ ,在Python中,如果一个属性的前面出现 __,就表示这个属性只能在当前类的方法中被直接访问,不能通过对象直接访问,这个变量就被称为私有变量

class Dog:
    def __init__(self,name,gender,age):
        self.name = name
        self._gender = gender  #'保护'变量
        self.__age = age    #私有变量
    #定义一个公开的方法,间接访问私有变量
    def get_age(self):
        return self.__age
     #定义一个公开方法,间接设置私有变量
    def set_age(self,age):
        self.__age = age
ding = Dog('丁丁','公',5)
print(ding.name)
# print(ding.__age) #AttributeError: 'Dog' object has no attribute '__age'
print(ding.get_age())  #5  获取私有属性的值
ding.set_age(10)   #设置私有属性的值
print(ding.get_age()) #10
print(ding._gender)

#可以通过 _Dog__age访问私有变量,但不建议
print(ding._Dog__age)

【面试题】
常见的在变量的前后加下划线的问题:
单下划线:_age  ----->受保护的 可以访问,当约定俗称,当你看到一个下划线开头的成员时不应该使用它
双下划线:__age   ------>私有的
两边都双下划线:__age__ ------->系统内置变量

3.2 属性装饰器

​ 对于私有属性的访问,使用公开方法间接访问的方法太麻烦,python提供了一种便捷语法,属性装饰器,通过属性装饰器,可以很方便的对私有属性进访问,属性修饰器可以把方法属性化。

class Dog:
    def __init__(self,name,gender,age):
        self.name = name
        self._gender = gender
        self.__age = age
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        self.__age =age

ding = Dog('丁丁','公',5)
print(ding.name)
print(ding.age)
ding.age =10
print(ding.age)
print(ding._gender)

3.3 成员方法私有化

​ 如果对一个方法的名字前面加__,声明该方法为私有方法,只能在当前类中被调用,在外界不能通过对象直接调用,这就是私有方法

class Dog:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __pee(self):
        print('这是我的地头')

dog = Dog('dingding',5)
#dog.__pee()  #AttributeError: 'Dog' object has no attribute '__pee'

4 构造和析构

4.1 构造方法

  • 目的:构造方法用于初始化对象(不创建对象),可以在构造方法中添加成员属性

  • 时机:实例化对象的时候自动调用

  • 参数:第一个参数必须是self,其它参数根据需要自己定义

  • 返回值:不返回值,或者说返回None,不应该返回任何其他值

    语法:
    	def __init__(self,arg1,arg2....):
    		函数体
    #参数:arg1,agr2...根据需要自己定义
    #如果自己不定义构造方法,系统自动生成一个构造函数
    def __init__(self):
      pass
    

注意:

  • 如果没有定义构造方法,系统会生成一个无参构造方法,如果自己定义了构造方法,则系统不会自动生成

    class 类名:
       def __init__(self):
       	    pass
    
  • 一个类只能有一个构造方法,如果定义多个,后面的会覆盖前面的

  • 构造函数由系统在实例化对象时自动调用,不要自己调用

    class Dog(object):
        def __init__(self,name,kind,age):
            self.name = name  #定义对象属性,这个类所有的对象都具有该属性
            self.kind = kind  #成员属性必须通过self.引用,否则是普通变量
            self.age = age
    
        def bark(tmp):
            print('我是小可爱--丁丁')
    
    dingding = Dog('丁丁','泰迪',3)
    print('我是可爱的%s犬,%s,我今年%d岁了' % (dingding.kind, dingding.name, dingding.age))
    

4.2 析构方法

  • 目的:对象销毁时,释放资源

  • 时机:对象销毁时由系统自动调用

  • 参数:除了self外,没有其他参数

  • 返回值:不返回值,或者说返回None。

  • 语法:

    def __del__(self):
        #to do
    
    class Dog(object):
    	#构造
        def __init__(self,name,kind,age):
            self.name = name
            self.kind = kind
            self.age = age
        #析构
        def __del__(self):
            print('拜拜了,二十年后又是一条好汉')
        def bark(tmp):
            print('我是小可爱--丁丁')
    
    dingding = Dog('丁丁','泰迪',3)
    print('我是可爱的%s犬,%s,我今年%d岁了' % (dingding.kind, dingding.name, dingding.age))
    del dingding  #销毁对象,自动调用析构方法
    
    #在函数中对象,当函数结束运行时,自动析构
    def test():
        td = Dog('当当','泰迪',3)
    

4.3 __str__

  • 目的:将对象转化为字符串
  • 时机:凡是涉及对象向字符串转换的都会调用(print,str)
  • 参数:self
  • 返回值:字符串

__repr__ 作用同__str__,不过是给解释器看的

class Animal:
    def __init__(self,name,age):
        self.name = name
        self.__age =age
    def __str__(self):
        return "name : {} age : {}".format(self.name,self.__age)
    def __repr__(self):
        return  self.__str__()
a1 = Animal('zhu',3)
print(a1)
print('我是一头可爱的 ' + str(a1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黎丶辰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值