17. 面向对象与封装

面向对象(object oriented)

面向对象基础

面向过程的编程思想:将程序流程化

  • 优点:将程序流程化,进而使程序设计简单化
  • 缺点:可扩展性差

面向对象的编程思想:对象就是容器,用来封装一些数据和功能,将程序进行整合,数据对应的就是属性,功能对应的是函数

  • 优点:提升程序的解耦合程度,进而增强程序的可扩展性
  • 缺点:设计复杂

面向对象编程相比较面向过程编程,能有效减少代码的重用性,增强代码的可读性

python中如何实现面向对象:类和对象

类(class)和对象(objcct)

在程序设计的时候,一定是先定义类,然后再调用类创建对象

# 1. 定义类 : 类是对象相同或者相似度功能的集合体,所以类中最常见的是变量与函数的定义,但是实际上类中可以使用任何代码
# 注意:在类的定义阶段就会执行代码,也就是说,类定义的时候就会产生类的名称空间,使用print(Student.__dict__)返回一个字典,可以查看类的名称空间中存放的东西
class Student:  # 驼峰体命名,首字母一般大写
	def __init__(self,name,age,gender)
    self.stu_name=name  # 根据3. 的解释就是将对象传给self,self.stu_name=name实际上就是对象.stu_name=name
    self.stu_age=age
    self.stu_gender=gender
    def tell_stu_info(self):
        print(self.stu_name)  
# 属性查看的方法:Student.stu_school、Student.tell_stu_info
# 查看全部的属性使用Student.__dict__

# 2. 类的调用会产生对象
stu1=Student()
# 类的名称空间和对象的名称空间的关系:类在定义的时候就会产生类的名称空间,存放类中的属性和函数,在进行实例化(就是调用类产生对象的过程)的时候,会产生一个对象名称的命名空间,里面存放一个指针,指向原来的类的命名空间,对象中如果使用原来的类的属性或者方法的时候,会通过指针直接在类的命名空间中寻找,但是对于对象自己的属性(对象可以自定义属性或者函数,马上讲),存放在属性的名称空间中,这和前面的容器类的数据类型的存储方式有点像,所以说实际上类也是一个容器

# 3. __init__方法(initial初始化的意思)
# 调用类的过程称为实例化,调用类的过程中一共发生了三件事:首先是产生一个对象的名称空间,然后会自动调用类中的init方法,将空对象和调用类时使用的参数一起传给init,最后,返回一个初始化之后得到的对象(init里面经过初始化的属性都有了)
# init的方法是定义类之后自动调用的,所以不要添加一些乱七八糟的代码
# init部分默认返回none,也必须返回none,所以不用return任何值

# 4. 属性的查找循序
# 属性的查找是从对象中开始的,对象中没有的属性会到类中去查找
# 类中的属性是实例化的对象所共享的,id都是一样的,这里涉及一个修改值的问题,如果直接修改类的属性,name所有对象所使用的属性都改变了,当只改变对象的属性时,会在对象的名称空间中创建一个属性的名,然后将修改的值赋值给它
# 类里面的函数是绑定给对象的,也就是说对象是将类的函数复制一份到自己的名称空间中,使用的时候直接调用自己名称空间中的函数,内存地址也各不相同,类里面的函数叫做函数,复制过来的对象里面的函数叫做绑定函数(bound method),实际上在定义类的时候,将函数里面放一个参数(self或者是obj都可以)的目的就是在对象使用函数的时候,将对象当做参数传给类中的函数中的参数self(因为函数中可能会使用到对象的属性),进而调用函数
# 在python中一切皆对象

面向对象的三大特性之封装

封装的实现主要是隐藏属性和开放接口实现的

# 1. 将封装的属性进行隐藏
class Person:
    def __init__(self,name,age):
    	self.name=name
        self.__age=age
    def __pick(self):
        pass
# 经过隐藏的属性和方法在外部是无法访问的(Person.age外面直接访问会报错),但是不是不能访问,Person._Person__age就可以访问隐藏属性(两个person都是类名)
# 这种隐藏实际上就是一种变形,你在定义的时候保存的不是self.__age=age,而是self._Person__age=age,同理方法也是经过了变形,但是这种变形对于用户来说是保密的,相对比较安全,这种隐藏在外部是不能直接访问的,但是在类的内部能够直接访问(方法可以直接使用self.__age)

# 隐藏属性的用途:隐藏数据属性使用户无法会直接查看和修改属性,程序员可以根据需求,用函数开放接口让用户查看属性,(def pick(self):print(self.__name)),程序设计者可以根据需求任意在函数中添加想要的逻辑,对于隐藏函数,可以保护一些关键的功能不被用户使用和发现(比如银行卡的一些操作)
'''
隐藏属性和隐藏函数介绍:
	隐藏属性实际上是在函数定义时完成的变形
	函数定义时会将定义时前面带有双下划线的属性和函数包装成“_类名__属性”的形式
	这种做法在一定程度上隐藏了属性和函数,在外部无法直接访问,但是一旦掌握原理,通过“_类名__属性”还是能够访问到的
	实际上在应用时这是一种约定俗成,放你看到下划线定义隐藏属性和函数的时候,记得不要将其进行更改
'''

property装饰器

# 1. property的用法1
class Perple:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
    # bmi是一个体质指数,实际上应该是一个属性,但是需要进行计算
    def bmi(self):
        return self.weight/(self.height**2)
    
person1=Perple('dabai',80,170)
print(person1.bmi())
# 下面就将bmi伪装成一个属性,property能够将一个函数伪装成一个属性
	@property
	def bmi(self):
		return self.weight/(self.height**2) 
# 这样直接访问person1.bmi能够直接将函数的返回值打印出来,像一个属性一样进行查看

# 2. property的用法2
class People:
    def __init__(self, name):
        self.__name = name
    def get_name(self):
        return self.__name
    def set_name(self, val):
        if type(val) is not str:
            print('必须传入str类型')
            return
        self.__name = val
    def del_name(self):
        print('不让删除')
        # del self.__name
    name=property(get_name,set_name,del_name)
obj1=People('dabai')
print(obj1.name)  # 进行查看的功能
obj1.name=18  # 进行修改的功能
del obj1.name # 进行删除的功能

# 3. property的用法3
class People:
    def __init__(self, name):
        self.__name = name
    @property
    def name(self): # obj1.name
        return self.__name
    @name.setter
    def name(self, val): # obj1.name='EGON'
        if type(val) is not str:
            print('必须传入str类型')
            return
        self.__name = val
    @name.deleter
    def name(self):
        print('不让删除')   
obj1=People('dabai')
print(obj1.name)  # 进行查看的功能
obj1.name=18   # 进行修改的功能
del obj1.name  # 进行删除的功能

静态方法@stasticmethod

  • 静态方法是一种非绑定方法,该方法不与类或对象绑定,类与对象都可以来调用它,但它就是一个普通函数而已,因而没有自动传值那么一说
'''
静态方法是直接在类中定义一个方法,这个方法谁都可以使用
class Staticmethod_Demo():
    role = 'dog'
    @staticmethod
    def func():
        print("当普通方法用")
Staticmethod_Demo.func()

静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互
即在静态方法中,不会涉及到类中的方法和属性的操作
可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护
'''
posted @ 2021-11-05 22:42  奇点^  阅读(62)  评论(0)    收藏  举报