008、面向对象

#面向对象 (解决问题的思路)


def 函数名():   #定义一个函数的方式
    xxxx

class 类名(object):      #定义一个类的方式
    xxxxx

1、类名命名规则 :大驼峰   定义类时有2种:新式类和经典类,上面的Car为经典类,如果是Car(object)则为新式类


2、类包含三部分 (类名  、 属性(修饰及信息 )  、方法(可以干什么(行为/功能))  ) 


3、创建对象:对象名 = 类名()  


4、设置或获取属性值,要重新定义一个方法  这样安全些  


5、获取这个对象的属性,2种方法:
01. 对象.属性
02. 定义一个方法,这个方法中,使用 self.属性


6、调用对象的方法(实例方法):对象名.方法()   


7、__init__()方法:
    1. 是python自动调用的方法,调用的时间为:创建完对象之后,立马自动调用
    2. 不需要开发者调用,即 对象名.__init__()
    3. 这个方法一般情况下会完成一些默认的事情,比如添加一些属性
        class Xxxx:
            def __init__(self, new_a, new_b):
                self.a = new_a
                self.b = new_b

        注意:new_a、new_b 是局部变量,并不是对象的属性,如果想在__init__方法中添加属性的话,需要使用类似
        self.属性名 = 值的格式,此时self.a = new_a表示的是给对象添加一个属性,这个属性名为a,这个属性的值为局部变量new_a里面的值


__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)

__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去


8、__str__()   :

    return  我们想要打印的东西     #打印的东西 不是地址  而是我们想要打印的东西    

在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法

当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据

 def __str__(self):
        msg = "嘿。。。我的颜色是" + self.color + "我有" + int(self.wheelNum) + "个轮胎..."
        return msg

如果一个对象保存了另一个对象以及另一个对象的引用,可以调用另一个对象所有的属性和方法


为了更好的保存属性安全,即不能随意修改,一般的处理方式为

  • 将属性定义为私有属性
  • 添加一个可以调用的方法,供调用

Python中没有像C++中public和private这些关键字来区别公有属性和私有属性

它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。


9、 __del__()   当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

  • 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
  • 当使用del删除变量指向的对象时,如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除

10、继承 (单继承 、多继承)

    注意点:
                子类在继承的时候,在定义类时,小括号()中为父类的名字
                父类的属性、方法,会被继承给子类(隐私属性和隐私方法无法调用)

私有的属性,不能通过对象直接访问,但是可以通过方法访问

私有的方法,不能通过对象直接访问

私有的属性、方法,不会被子类继承,也不能被访问

一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用

所谓多继承,即子类有多个父类,并且具有它们的特征


11、重写父类方法与调用父类方法

            01. 重写父类方法       所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

           02. 调用父类的方法      

 # 调用父类的__init__方法
   super().__init__(name)
   super().父类的方法名() Python3用这种  

 

多态:所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态

            Python是弱类型语言  多态不明显   

 


12、面向对象编程三种特性  :封装(类)  继承(相同的类) 多态(定义和调用的方法可能不一样)  


13、类属性、实例属性   (类属性(跟着类走,在方法外面,类里面)  实例属性(跟着实例走)

公有的类属性,在类外可以通过类对象实例对象访问

class People(object):
    name = 'Tom'  #公有的类属性
    __age = 12    #私有的类属性

p = People()

print(p.name)           #正确
print(People.name)      #正确
print(p.__age)          #错误,不能在类外通过实例对象访问私有的类属性
print(People.__age)     #错误,不能在类外通过类对象访问私有的类属性

如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。(通过  类名.类属性=  *  可以修改类属性的值  如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性

class People(object):
    country = 'china' #类属性


print(People.country)
p = People()
print(p.country)
p.country = 'japan' 
print(p.country)      #实例属性会屏蔽掉同名的类属性
print(People.country)
del p.country         #删除实例属性
print(p.country)

14、静态方法和类方法

01. 类方法

类方法是类对象所拥有的方法,需要用修饰器{ @classmethod }  来标识其为类方法 ,对于类方法,第一个参数必须是类对象, 一般以cls ,作为第一个参数 ,能够通过实例对象和类对象去访问。

class People(object):
    country = 'china'

    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country

p = People()
print p.getCountry()         #可以用过实例对象引用
print People.getCountry()    #可以通过类对象引用

用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变


02. 静态方法

          需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数

class People(object):
    country = 'china'

    @staticmethod
    #静态方法
    def getCountry():
        return People.country


print People.getCountry()

            注意点: 用类名 调用 类方法和静态方法  可读性更高
                           不允许 使用类名访问实例属性 、实例方法


15、工厂模式

01、简单工厂方法:  解耦  模块化  使功能更加单一

Python3创建一个类的时候要明确(object)

02、工厂方法:基类不实现     通过子类重写部分代码实现 


16、__new__方法

class A(object):
    def __init__(self):
        print("这是 init 方法")

    def __new__(cls):
        print("这是 new 方法")
        return object.__new__(cls)

A()

__new__(cls) 完成对象的创建  

01  __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

02  __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
return  object.__new__(cls)  或者是return super().__new__(cls)

03   __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

04   我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节。


17、单例模式 

通过 对__new__()以及 __init()修改 达到创建的对象指向同一片区域

cls =“类名”


18、异常       异常就是程序崩了

01、捕获异常: try...  except ....  

try:
    可能出现异常的代码

except  异常1:
    处理的方式1

except  异常2:
    处理的方式2

except  (异常1,异常2):
    捕获多个异常同一个处理的方式

except  异常 as result:
    print("产生了一个异常...%s"%result)   #打印系统默认捕获的异常的信息


except  (异常1,异常2) as result:
    print("产生了一个异常...%s"%result)   #打印系统默认捕获的异常的信息


02、捕获所有异常并打印系统默认提示异常信息:

try:
    可能出现异常的代码

except  Exception as result:
    处理的方式


03、try ...else  :

try:
    可能出现异常的代码

except  异常:
    处理的方式

else:
    如果try里没有产生异常执行的事情


04、try ...finally  :

try:
    可能出现异常的代码

except  异常:
    处理的方式

finally :
    任何情况下,不管有没有异常都要做的事情


05、异常的传递:

如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。。。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样


06、异常处理中抛出异常   (利用一个变换的变量,先保存异常然后把异常抛出)


07、抛出自定义异常

raise  继承Exception创建的类(自定义的异常)     从键盘获取一个值,根据值的长度是否符合要求而选择是否抛出异常

class ShortInputException(Exception):
    '''自定义的异常类'''
    def __init__(self, length, atleast):
        super().__init__()
        self.length = length
        self.atleast = atleast
try:
    s = input('请输入 --> ')
    if len(s) < 3:
        # raise引发一个你定义的异常
        raise ShortInputException(len(s), 3)

except EOFError:
    print("你输入了一个结束标记EOF")
except ShortInputException as result:#x这个变量被绑定到了错误的实例
    print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (result.length, result.atleast))
else:
    print('没有异常发生.')

注意

  • 以上程序中,关于代码#super().__init__()的说明

    这一行代码,可以调用也可以不调用,建议调用,因为__init__方法往往是用来对创建完的对象进行初始化工作,如果在子类中重写了父类的__init__方法,即意味着父类中的很多初始化工作没有做,这样就不保证程序的稳定了,所以在以后的开发中,如果重写了父类的__init__方法,最好是先调用父类的这个方法,然后再添加自己的功能


19、模块  (具有特殊功能的代码块(.py文件))

 --------01>导入模块:   引用方式为:模块名.函数名(模块.功能)

01、import  模块的名称     demo:    import  random      

02、from  ....import.....    demo:   from  random  import randint   不会把整个random模块导入到当前的命名空间中,它只会将模块里randit的单个引入

03、from … import *      demo:   from  random  import   *    这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。


模块测试+调用代码:

自己测试的时候执行 if后面的代码 (打出来是__main__)  别人调用的时候(打出来是导入的模块的名字)不执行if后面的代码

if __name__ == "__main__":
    main()

import导入模块时,生成pycache  


20、模块中的__all__

1. 没有__all__

2. 模块中有__all__    __all__ =[导入的内容]   后期别的程序调用的时候只能调用导入的内容


21、Python中的包:

将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py  文件,不管__init__.py 文件是否为空,整个文件夹称之为包

(一般文件夹内含有 __init__.py 文件 且__init__.py 文件内写入变量---->__all__  =[“模块名”] 内容,如果__init__.py 文件为空,仅仅是把这个包导入,不会导入包中的模块,之所以定义一个__all__变量,因为它控制着 from 包名 import *时导入的模块)

有效避免模块名称冲突问题,让应用组织结构更加清晰


 set 是集合  里面的值不允许相同  

b=set(a)     使用set,可以快速的完成对list中的元素去重复的功能


给程序传参数

import sys

print(sys.argv)

sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,所以那些试图从代码来说明它作用的解释一直没看明白。因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数。

sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该将程序保存了,从外部来运行程序并给出参数。


列表推导式: 所谓的列表推导式,就是指的轻量级循环创建列表

a=[x for x  in range(1,11)]     生成一个1-10的列表

a=[x for x  in range(1,11)  if x%2==0  ]     生成一个1-10 偶数的列表

a=[(x,y) for x  in range(1,4) for y  in range(1,3) ]     生成  [(1, 1), (1, 2), (2, 1), (2, 2), (3, 1), (3, 2)]   的列表


字典推导式 (更换key value值)  

mcase = {'a': 10, 'b': 34}
mcase_frequency = {v: k for k, v in mcase.items()}
print mcase_frequency
#  Output: {10: 'a', 34: 'b'}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值