ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python面向对象编程

2022-01-24 11:34:04  阅读:109  来源: 互联网

标签:__ .__ Python self 面向对象编程 print def 属性


01.基本理论

一、对象的概念

1.万物皆对象

2.对象是一个具体的物体

拥有的属性、拥有的行为、零散的封装成一个整体。例如:王小二(属性:姓名、年龄、身高...行为:走路、吃饭、放羊...)

3.对象在python中的体现

python是一门特别彻底的面向对象编程(OOP)的语言( 其它语言包括基本数据类型与对象类型)

二、面向过程与面向对象的区别

1.面向过程与面向对象的编程思想

他们都是属于一种解决问题的思路。

面向过程:在解决问题的时候,关注的是解决问题的每一个过程(步骤)

面向对象:在解决问题的时候,关注的是解决问题所需要的对象

例如:吃完饭之后洗碗(面向过程:放水、放碗、倒洗洁精、刷、擦干;面向对象:你的技能、你对象的技能...)

2.面向过程与面向对象的对比

1)面向对象和面向过程都是解决问题的一种方式(思想),面向对象是面向过程的一种封

2)面向过程编程最重要的是:把一个任务分解成具体的步骤。

3)面向对象编程最重要的是:按照对象的功能进行划分,找到对象确定对象的属性和行为。

3.从面向过程编程的思想过渡到面向对象编程的步骤

1)列举出一个任务具体的实现步骤;

2)试图分离这些实现步骤中的功能代码;

3)将这些功能代码块,划分都某一个对象中;

4)根据这个对象以及对应的行为,抽象出对应的类;

三、类的简介

1.什么是类

某一个具体对象特征的抽象

2.类的作用

根据抽象的类,生产出具体的对象

例如:(类:不良青年 属性:年龄、身高、体重... 行为:吃喝嫖赌...对象:张三、李四、王五...都满足以上的属性和行为)

3.类的组成

名称、属性(静态的特征值)、方法(动态的动作)

注意:1)以上属性和方法,都是抽象的概念

           2)在产生对象之后,对象才拥有具体的属性值和方法实现

4.生活中常用的类

1)类:钱                    对象:具体的一块、两块、一百块...

2)类:汽车                对象:奥迪、宝马、奔驰...

5.对象和类的区别

对象——>抽象——>类——>实例化——>对象

02.面向对象编程在python中的实践

一、定义一个类(经典类、新式类)

class Money:		#class类名:(类名的首字母需要大写,不要加小括号)
    pass
class renminbi(money):		#括号内部表示继承关系

二、根据类创建一个对象

one =Money()		#one就是一个对象(通过*类名+一个括号*即可创建一个对象)
print(one)

三、创建对象时的底层运作

ProcessOn在线绘图(可以绘制流程图)

四、属性相关

1.属性和变量的区别及判定依据

1)区别:变量是“可以改变的量值”,根据不同的位置存在不同的访问权限(全局变量、局部变量)

                 属性是“属于某个对象的特性”,只能通过一个对象进行访问

2)判定依据:是否存在宿主

2.对象属性

1)添加操作:直接通过对象动态添加——>对象.属性=值

                       通过类的初始化方法(构造方法)——>int方法

2)查询操作

3)修改操作

4)删除操作

#定义一个类
class Person:
    pass
#根据这个类创建一个对象
p=Person()
#给对象p增加属性
p.age=18
p.height=180
#查找当前对象所有的属性(返回一个字典)
p.__dict__
#删除一个属性
del p.age

5)注意事项:不同对象之间不能访问其唯一的属性。

3.类属性

1)添加操作:类名.属性=值     ;在类里面写变量名=值

2)查询属性:既可以通过类进行查询,也可以通过对象进行查询

(python对象查找机制:优先到对象自身去查找属性,如果没有找到,则根据class找到对应的类,再在这个类里面进行查找)

3)修改属性:只能通过类名进行修改,不能通过对象进行修改

4)删除操作:只能通过类名进行删除,不能通过对象进行删除

5) 注意事项:类属性的内存存储问题;类属性被各个对象所共享

#在类里面添加属性
class Money:
    age=18
    count=1
    pass
class Text:
    sex=male
#更改对象所属的类
one=Money()
one.__class__=Text
#对类的属性的修改
Money.age=22
#删除类的属性
del Money.age

五、方法相关

1.方法的概念

1)方法的概念:描述一个目标的行为动作(比如描述一个人怎么吃、怎么喝...)和函数非常的类似

——>都封装了一系列行为动作

——>都可以被调用之后执行一系列行为动作

——>最主要的区别就是调用的方式不同

#函数
def eat():
    print(1)
    print(2)
    print(3)
eat()
#方法
class Person:
    def eat2(self):
        print(1)
        print(2)
p=Person()
p.eat2()

2.方法的划分

1)类、对象、实例、实例对象、实例化

2)方法的划分依据

实例方法:默认第一个参数需要接收到一个实例;

类方法:默认第一个参数需要接收到一个类;

静态方法:静静的看着前面两个在装逼,第一个参数啥也不默认接收;

注意:

—>划分的依据是第一个参数必须接收到的数据类型

—>不管是哪一种类型的方法,都是存储在类当中,没有在实例当中的

—>不同类型的调用方式不同

—>重点关注方法的使用层面:语法、不同类型方法的规则、不同类型的方法调用、根据不同的问题设计不同的方法解决问题

3)方法的存储问题

3.实例方法

1)标准形式

2)标准调用:使用实例调用实例方法(不用手动传,解释器会自动被调用对象本身传递过来)

             注意:如果实例方法没有接收到任何参数,则会报错。

#创建一个类+实例方法
class Person:
    def eat(self,food):
        print("在吃饭",food)
#标准调用
p=Person()
p.eat("土豆")
#————>输出:在吃饭,土豆

4.类方法

1)标准形式

2)标准调用:既可以通过类调用,也可以通过实例调用

#创建一个类+类方法
class Person:
    @classmethod		#类方法装饰器
    def leifangfa(cls,a):
        print("这是一个类方法",cls,a)
#标准调用(既可以通过类调用,也可以通过实例调用)
Person.leifangfa(123)
#—————>输出:这是一个类方法,<class'__main__.Person>123

5.静态方法

1)标准形式

2)标准调用:既可以通过类调用,也可以通过实例调用

#创建一个类+静态方法
class Person:
    @staticmethod
    def jingtai():
        print("这是一个静态方法")
#标准调用(既可以通过类调用,也可以通过实例调用)

6.不同类型的方法中访问不同类型属性的权限问题

class person:
    age=0
    def shilifangfa(self):
        print(self.age)
        print(self.num)
    @classmethod
    def leifangfa(cls):
        print(cls.age)
        print(cls.num)

p=Person()
p.num=10

p.shilifangfa()		#age和num属性全部能够输出
p.leifangfa()		#age属性能够输出,num属性会报错

六、补充

1.类相关补充

1)元类:创建类对象的类

2)类的描述:(用于规范编程)

  • 目的:方便自己理清逻辑思路、方便多人合作开发时的沟通、方便生成项目文档

  • 描述方式:在定义类、属性、方法下面一行写注释,使用双引号对(标明效果、 参数、参数含义、参数类型[动态语言参数不确定],是否有默认值, 返回值)

  • 生成项目文档:(不需要把源码全部给别人,先使用help()生成项目)

              方式一,使用python内置模块pydoc(参考课程,现学现用)

              方式二,使用第三方模块Sphinx、epydoc、doxygen(参考课程,现学现用)

2.属性相关补充

1)私有化属性(对访问范围较大的属性设置一个范围,使其访问范围较小)

                可用于数据保护以及数据过滤

  • 注意:python中并没有真正的私有化支持(只是通过名字重整规则加密了),但是可以使用下划线完成伪私有效果(使用其他的手段进行访问); 类属性(方法)和实例属性(方法)遵循相同的规则

  • 公有属性(x):类内部访问——>可以

                               子类内部访问——>可以

                               模块内其他位置访问 类访问——>警告

                                                                 实例访问——>警告

                                跨模块访问 import——>可以

                                                   from 模块 import *——>可以

  • 受保护的属性(_y):类内部访问——>可以

                                           子类内部访问——>可以

                                           模块内其他位置访问 类访问——>可以

                                                                             实例访问——>可以

                                           跨模块访问 import——>报错

                                                              from 模块 import *——>报错

#file1
_a=6
#file2
from file1 import *
print(_a)			#受保护会报错
###########################################################################################
#file1
_a=6
__all__=['_a']		#内置属性__all__可用来传输受保护参数
#file2
from file1 import *
print(_a)		#可以正常访问
  • 私有属性(__z):   类内部访问——>可以

                                       子类内部访问——>报错

                                       模块内其他位置访问 类访问——>报错

                                                                          实例访问——>报错

                                        跨模块访问 import——>报错

                                                           from 模块 import *——>报错

                          注意:也可以使用__all__=['']使其他模块进行访问

  • 补充: x_       与系统内置的关键字做区分

                 _ _x__   系统内置的特殊属性(例如:__dict__、__count__)

2)只读属性(一个属性【一般指实例属性】只能读取不能写入)

有些属性只限于内部根据不同场景进行修改,而对外界来说不能修改,只能读取。

 例如:电脑类的网速属性、网络状态属性。

  • 设置只读属性(方案一):全部隐藏,部分公开【这里就会用到@property修饰器】

                首先通过“属性前置双下划线”实现,再通过公开的方法进行部分公开。

class Person(object):
    def __init__(self):
#全部隐藏
        self.__age=18

#部分公开
    @property        #主要作用就是可以使用属性的方式来使用这个方法
    def age(self):
        return self.__age

p=Person()
print(p.age)


'''
经典类与新式类(建议使用新式类)
经典类:没有继承(object)
新式类:有继承(object)
        可以通过'__bases__'查询继承类
python2.x 如果定义一个类,没有显示继承自object,那么这个类就是一个经典类。
python3.x 无论有没有显示继承,默认都是一个新式类
'''
'''
@property 装饰器讲解 
1.主要作用:将一个些“属性的相关方法(删、改、查)”关联到某一个属性中。常用于定义或管理__X
2.property在新式类中的使用:(代码1)
3.property在经典类中的使用:(代码2)(一般不使用,随用随听)
'''

#代码1
class Person(object):
    def __init_(self):
        self.__age=18
    @property        ##########装饰器1:(查)
    def age(self):
        return self.__age
    @age.setter        #########装饰器2:(改)
    def age(self,value)
        self.__age=value
    @age.deleter       #########装饰器3:(删)
    def x(self):
        del self.__age                      
                             
p=Person()
print(p.age)
print(p.age=90)
  • 设置只读属性(方案二)
class Person:
    def __setattr__(self,key,value):
    #当我们通过 实例.属性=值 时,给一个实例增加一个属性或者说修改一个属性值的时候,都会调用这个方法
    #在这个方法内部,才会真正把这个属性以及对应的数据存储到__dict__字典里面。
        print(key,value)
        #第一步:判定key是否是我们要设定的只读属性的名称。
        if key=='age' and key in self.__dict__.keys():
            print('这个属性是只读属性,不能设置数据')
        #第二部:如果不是只读属性的名称,则真正的给它添加到这个实例里面去。
        else:
            self.__dict__[key]=value

3)内置特殊属性(当定义好一个类或通过这个类创造了一个实例,系统自动的分配了一些可以直接使用的属性,以完成一些小的测试操作或某些应用场景)

  • 类属性:__dict__:类的属性

                      __bases__:类的所有父类元组(python是多继承,java是单继承)

                      __doc__:类的文档字符串

                      __name__:类名

                      __module__:类定义所在的模块

  • 实例属性:__dict__:实例的属性

                         __class__:实例对应的类

class Person:
    age=19                        #类属性
    def __init__(self):
        self.name='sz'            #利用初始化方法定义一个实例属性
    def run(self):
        print("run")
print(Person.__dict__)
print(Person.__bases__)
print(Person.__doc__)
print(Person.__name__)
print(Person.__module__)


P=Person()
print(P.__dict__)
print(P.__class__)

 2.方法相关补充

1)私有化方法(同于私有化属性:名称重整机制)

                当类的内部才使用的方法,且不暴露给外界使用。

2)内置特殊方法

  • 生命周期方法(下一节单独介绍)
  • 信息格式化操作:__str__方法:面向用户

                                    __repr__方法:面向开发人员、python解释器

class Person:
    def __init__(self,n,a):
        self.name=n
        self.age=a
    def __str__(self):
        return "这个人的姓名是:%s,这个人的年龄是:%s"%(self.name,self.age)

p1=Person("sz",18)
p2=Person("zs",19)

print(p1)        #此时打印的就不再是模块名+类名+内存地址,而是__str__方法,return的返回值
print(p2)
print(repr(p1))        #当有__str__方法时,用此方法可打印模块名+类名+内存地址
print(repr(p2))
  • 调用操作:__call__方法                使得实例化的对象具有被调用的能力
class Person:
    def __call__(self,*args,**kwargs):
'''
    使用用__call__方法,使得实例化的对象具有被调用的能力。
    *args  为元组的形式
    **kwargs  为字典形式
    这两个参数保证了可以传输任何形式
'''
        print("xxx",args,kwarge)
    pass
p=Person
p(123,456,name='sz')    #若类中没有__call__方法,则会报错;若有__call__方法,则会调用__call__的方法。
  • 索引操作
  • 切片操作
  • 迭代器
  • 描述器

03.面向对象编程——综合案例

#任务:做一个计算器,实现一些基本操作,加减乘除以及打印结果
#面向过程编程,对于连续运算极其复杂,不安全

#设计以及优化思路:包装——>安全性——>能否满足多个同时运算——>是否容错(健壮性)
class Cacular:
    def __int__(self,num):		#用于初始化一个类,num是初始化的属性值
        if not isinstance(num,int):	  #Python中的 isinstance() 函数,是Python中的一个内置函数,用来判断一个函数是否是一个已知的类型,类似 type()。
            raise TypeError("当前这个数据类型有问题,应该是一个整型数据。") 
    #当程序出现错误,python会自动引发异常,也可以通过raise显示引发异常,并通过TypeError()给出提示语。一旦执行了raise语句,raise后面的语句将不能执行。
        self.__result=num		#“__”是私密化处理,实例只能调用、查询,不能修改
    def jia(self,n):
         if not isinstance(num,int):
            raise TypeError("当前这个数据类型有问题,应该是一个整型数据。")
        self.__result+=n
    def jian(self,n):
         if not isinstance(num,int):
            raise TypeError("当前这个数据类型有问题,应该是一个整型数据。")
        self.__result-=n
    def cheng(self,n)
     if not isinstance(num,int):
            raise TypeError("当前这个数据类型有问题,应该是一个整型数据。")
        self.__result*=n
    def show(self):
        print("计算的结果是:%d"%self.__result)
c1=Cacular(2)
c1.jia(6)
c1.jian(4)
c1.cheng(5)
c1.show()
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#进一步优化思路:以上代码太过冗余,需要简化————>装饰器(不改变原来的代码基础)————>装饰器私有方法
class Cacular:
    def __check_num_zsq(func):		#私有方法的装饰器
        def inner(self,n):
            if not isinstance(num,int):
            	raise TypeError("当前这个数据类型有问题,应该是一个整型数据。")
            return func(self,n)		######################################################不太明白!!!
        return inner
    @__check_num_zsq		#装饰器
    def __int__(self,num):
        self.__result=num
    @__check_num_zsq
    def jia(self,n):
        self.__result+=n
    @__check_num_zsq
    def jian(self,n):
        self.__result-=n
    @__check_num_zsq
    def cheng(self,n)
        self.__result*=n
    def show(self):
        print("计算的结果是:%d"%self.__result)
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#增加一个新任务:每一步都实现语音播报功能(类似与开启声音的计算器)
#既可以通过安装第三方库实现,也可以通过调用Windows操作系统的接口
#设计以及优化思路:在哪里插入代码——>简化代码————>采用装饰器,不破坏原有的结构(嵌套装饰)
import win32com.client
class Cacular:
    def __check_num_zsq(func):		#私有方法的装饰器
        def inner(self,n):
            if not isinstance(num,int):
            	raise TypeError("当前这个数据类型有问题,应该是一个整型数据。")
            return func(self,n)		######################################################不太明白!!!
        return inner
    def __say(self,word):
        spearker=win32com.client.Dispatch("SAPI.ApVoice")		#创建一个播报对象
        speaker.Speak(word)			#通过这个播报器对象,直接播放对应的语音字符串即可
    def __creat_say_zsq(word=""):
        def __say_zsq(func):
            def inner(self,n):
                self.__say(word+str(n))
                return func(self,n)
            return inner
        return __say__zsq
    @__check_num_zsq		#装饰器
    @__creat_say_zsq()
    def __int__(self,num):
        self.__result=num
    @__check_num_zsq
    @__creat_say_zsq("加")
    def jia(self,n):
        self.__result+=n
    @__check_num_zsq
    @__creat_say_zsq("减去")
    def jian(self,n):
        self.__result-=n
    @__check_num_zsq
    @__creat_say_zsq("乘以")
    def cheng(self,n)
        self.__result*=n
    def show(self):
        self.__say("计算的结果是:%d"%self.__result)
        print("计算的结果是:%d"%self.__result)

c1=Caculator(10)
c1.jia(6)
c1.jian(4)
c1.cheng(5)
c1.show

标签:__,.__,Python,self,面向对象编程,print,def,属性
来源: https://blog.csdn.net/m0_57385293/article/details/122651093

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有