博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python:面向对象(二)
阅读量:4708 次
发布时间:2019-06-10

本文共 11009 字,大约阅读时间需要 36 分钟。

  • 扩展:

 继承:

class A:    def f(self):        self.f1()class B(A):    def f1(self):        print("B")class C:    def f1(self):        print("C")class D(C,B):  passd1 = D()d1.f()#打印结果:C#执行顺序:D-C-B-A-A-C

 执行顺序图:

 

练习:

注:一定记住从底层开始找

####实例:找源码的过程(self.xxx(),从底层开始找)####import socketserverr = socketserver.ThreadingTCPServer()r.serve_forever()
找源码

 

执行父类的构造方式:

    类名加括号执行类的普通字段:__init__

    推荐:super(当前类,self).__init__()

    不推荐:父类.__init__(self)

class Animal:    def __init__(self):        print("A构造方法")        self.ty = "动物"class Cat(Animal):    def __init__(self):        print("B构造方法")        self.n = "猫"        super(Cat,self).__init__()c = Cat()print(c.n)#打印结果:B构造方法A构造方法猫##########c = Cat()print(c.__dict__)#打印结果:B构造方法A构造方法{
'ty': '动物', 'n': '猫'}

 

 

 

 

  • 面向对象的进阶

一、成员

 类的成员可以分为三大类:字段、方法、属性

 

 字段

字段包括普通字段和静态字段,两者在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。

  • 静态字段属于
  • 普通字段属于对象

  注:静态字段:调用

    普通字段:对象调用

class Foo:    # 静态字段,在类里(没有self),由类调用    country = "中国"    # 普通字段,封装在对象中,由对象调用    def __init__(self,name):        self.name = name    # 普通方法,在类里,由对象调用    def show(self):        print("show")print(Foo.country)obj = Foo("北京")print(obj.name)obj.show()#打印结果:中国北京show

应用场景:通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段。

 

 方法

 方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,但是调用方式有所不同。

注:

普通方法:对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self

静态方法:调用,没有默认参数,可以添加参数。关键字:@staticmethod

类方法:调用,至少一个cls参数,执行类方法时,自动将调用该方法的类名复制给cls。关键字:@classmethod

class Provice:    # 静态字段    country = "China"    # 普通字段    def __init__(self):        self.name = "China"    # 类方法    @classmethod    def f1(cls):        print("F1")    # 静态方法    @staticmethod    def f2():        print("F2")    # 普通方法    def show(self):        print("show") obj = Provice()obj.show() # 用对象调用普通方法Provice.f1() # 用类调用类方法,默认参数为clsProvice.f2() # 用类调用静态方法,默认无参数#打印结果:showF1F2

 

属性

  Python中的属性其实是普通方法的变种。

属性的基本使用:

定义及调用:

  定义:仅有一个self参数,加参数会报错。关键字:@property

  调用:用对象调用属性,调用时不加括号

class Foo: def __init__(self):        self.name = "num"     def start(self):        print("start")    #定义属性    @property    def end(self):        print("end")obj = Foo()obj.start()obj.end#打印结果:startend

 

设置字段:字段是能获取也能重新设置:

class Foo:    def __init__(self,name):        self.name = name    @property    def end(self):        temp = "%s A" % self.name        return tempobj = Foo("num")#获取字段print(obj.name)#设置字段obj.name = "123"print(obj.name)#打印结果:num123

 

设置属性:属性是将方法伪造成字段(调用时不加括号):@方法名.setter

class Foo:    def __init__(self,name):        self.name = name    @property    def end(self):        temp = "%s A" % self.name        return temp    @end.setter    def end(self,value):        print(value)obj = Foo("num")print(obj.end) #获取end值obj.name = "123" #设置end值,执行@方法名.setter方法print(obj.end) #打印结果:num A123 A

 

 

二、成员修饰符

  •  公有成员,在任何地方都能访问

  • 私有成员,只有在类的内部才能访问

 私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外:__init__、__call__、__dict__等)

class C:     def __init__(self):        self.name = '公有字段'        self.__foo = "私有字段"

 

私有成员和公有成员的访问限制不同:

  静态字段

公有静态字段:类可以访问;类内部可以访问;派生类中可以访问

私有静态字段:仅类内部可以访问

class C:    name = "公有静态字段"    def func(self):        print C.nameclass D(C):    def show(self):        print C.nameC.name         # 类访问obj = C()obj.func()     # 类内部可以访问obj_son = D()obj_son.show() # 派生类中可以访问
公有静态字段
class C:    __name = "公有静态字段"    def func(self):        print C.__nameclass D(C):    def show(self):        print C.__nameC.__name       # 类访问            ==> 错误obj = C()obj.func()     # 类内部可以访问     ==> 正确obj_son = D()obj_son.show() # 派生类中可以访问   ==> 错误
私有静态字段
class Foo:    xo = "xo"    __xx = "xx"    def __init__(self):        pass    def f(self):        print(Foo.__xx)    def d(self):        print("d")print(Foo.xo)# print(Foo.__xx)#报错,有__只能内部执行obj = Foo()obj.f()#打印结果:xoxx

 

  普通字段

公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问

私有普通字段:仅类内部可以访问

ps:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。

class C:        def __init__(self):        self.foo = "公有字段"    def func(self):        print self.foo  # 类内部访问class D(C):        def show(self):        print self.foo # 派生类中访问obj = C()obj.foo     # 通过对象访问obj.func()  # 类内部访问obj_son = D();obj_son.show()  # 派生类中访问
公有普通字段
class C:        def __init__(self):        self.__foo = "私有字段"    def func(self):        print self.foo  # 类内部访问class D(C):        def show(self):        print self.foo # 派生类中访问obj = C()obj.__foo     # 通过对象访问    ==> 错误obj.func()  # 类内部访问        ==> 正确obj_son = D();obj_son.show()  # 派生类中访问  ==> 错误
私有普通字段
class Foo:    xo = "xo"    __xx = "xx"    def __init__(self):        self.__name = "name"    def f(self):        print(Foo.__xx)    def d(self):        print(self.__name)obj = Foo()obj.f()obj.d()#打印结果:xxname

 

 

三、面向对象中一些常用特殊方法

 1、__init__:构造方法,通过类创建对象时,自动触发执行。

class Foo:    def __init__(self, name):        self.name = name        self.age = 18obj = Foo('wupeiqi') # 自动执行类中的 __init__ 方法
__init__

 

2、__del__:析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:    def __del__(self):        pass
__del__

 

3、__call__:对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:    def __init__(self):        pass        def __call__(self, *args, **kwargs):        print '__call__'obj = Foo() # 执行 __init__obj()       # 执行 __call__
__call__

 

4、__getitem__、__setitem__、__delitem__:获取、设置、删除数据。用于索引操作,如字典。

class Foo(object):     def __getitem__(self, key):        print '__getitem__',key     def __setitem__(self, key, value):        print '__setitem__',key,value     def __delitem__(self, key):        print '__delitem__',key  obj = Foo() result = obj['k1']      # 自动触发执行 __getitem__obj['k2'] = '123'   # 自动触发执行 __setitem__del obj['k1']           # 自动触发执行 __delitem__
__getitem__、__setitem__、__delitem__

 

5、__dict__:类或对象中的所有成员。

class Province:    country = 'China'    def __init__(self, name, count):        self.name = name        self.count = count    def func(self, *args, **kwargs):        print 'func'# 获取类的成员,即:静态字段、方法、print Province.__dict__# 输出:{'country': 'China', '__module__': '__main__', 'func': 
, '__init__':
, '__doc__': None}obj1 = Province('HeBei',10000)print obj1.__dict__# 获取 对象obj1 的成员# 输出:{'count': 10000, 'name': 'HeBei'}obj2 = Province('HeNan', 3888)print obj2.__dict__# 获取 对象obj1 的成员# 输出:{'count': 3888, 'name': 'HeNan'}
__dict__

 

6、__iter__:用于迭代器,之所以列表、字典、元祖可以进行for循环,是因为类型内部定义了__iter__。

class Foo(object):    def __init__(self, sq):        self.sq = sq    def __iter__(self):        return iter(self.sq)obj = Foo([11,22,33,44])for i in obj:    print i
__iter__

 

7、__str__:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

class Foo:    def __str__(self):        return '123'obj = Foo()print obj# 输出:123
__str__

 

 

  • 异常处理

1、异常基础

程序出现bug时,一般不会将错误信息显示给用户,而是实现一个提示的页面。

异常处理格式:

1 try:2     pass3 except Exception as e:4     pass

练习:将用户输入的两个数字相加

while True:    num1 = input("num1:")    num2 = input("num2:")    try:        num1 = int(num1)        num2 = int(num2)        result = num1 + num2    except Exception as e:        print("出现异常,信息如下:")        print(e)
View Code

 

2、异常种类

异常种类,不同种类处理不同异常

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性xIOError 输入/输出异常;基本上是无法打开文件ImportError 无法引入模块或包;基本上是路径问题或名称错误IndentationError 语法错误(的子类) ;代码没有正确对齐IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]KeyError 试图访问字典里不存在的键KeyboardInterrupt Ctrl+C被按下NameError 使用一个还未被赋予对象的变量SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)TypeError 传入对象类型与要求的不符合UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它ValueError 传入一个调用者不期望的值,即使值的类型是正确的
常用异常
ArithmeticErrorAssertionErrorAttributeErrorBaseExceptionBufferErrorBytesWarningDeprecationWarningEnvironmentErrorEOFErrorExceptionFloatingPointErrorFutureWarningGeneratorExitImportErrorImportWarningIndentationErrorIndexErrorIOErrorKeyboardInterruptKeyErrorLookupErrorMemoryErrorNameErrorNotImplementedErrorOSErrorOverflowErrorPendingDeprecationWarningReferenceErrorRuntimeErrorRuntimeWarningStandardErrorStopIterationSyntaxErrorSyntaxWarningSystemErrorSystemExitTabErrorTypeErrorUnboundLocalErrorUnicodeDecodeErrorUnicodeEncodeErrorUnicodeErrorUnicodeTranslateErrorUnicodeWarningUserWarningValueErrorWarningZeroDivisionError
其他异常

 

实例:IndexError、KeyError、ValueError

########li = []try:    li[3]except IndexError as e:    print(e)########dic = {
"k1":"v1"}try: dic["k2"]except KeyError as e: print(e)########s = "hello"try: int(s)except ValueError as e: print(e)#打印结果:list index out of range'k2'invalid literal for int() with base 10: 'hello'

 

异常类只能用来处理制定的异常情况,如果非制定异常则无法处理

#未捕获到异常,程序直接报错s = "hello"try:    int(s)except ValueError as e:    print(e)

为了避免有其他异常,可以这样写:

s = "hello"try:    int(s)except IndexError as e:    print(e)except KeyError as e:    print(e)except ValueError as e:    print(e)

万能异常:因为异常不止几种,有一个万能异常,就可以捕获任意异常

s = "hello"try:    int(s)except Exception as e:    print(e)

 

虽然有万能异常,但是也不能只用万能异常就可以来了,因为对于特殊处理或提醒的异常需要先定义,最后再定义Exception来确保程序正常运行。

s = "hello"try:    # li = []    int(s)except IndexError as e:    print(e)except ValueError as e:    print(e)except Exception as e:    print("123")

 

3、异常其他结构

分两种情况:

a:try --> exceot KeyError as e --> finally

b: try --> else --> finally

try:    # 主代码块    passexcept KeyError as e:    # 主代码异常时,执行该块    passelse:    # 主代码块正常时,执行完,执行该块    passfinally:    # 无论异常与否,最终执行该块    pass

 

4、主动触发异常

 

try:    print("123")    raise Exception("出错了...")except Exception as e:    print(e)#打印结果:123出错了...

 

5、断言

 

#assert 作为关键字#条件成立就执行assert 1 == 1 #条件不成立就报错assert 1 == 2

 

作业:选课(对象中可以封装对象) 

特性补充:

 方法一:装饰器+方法

class Foo:    def func(self):        print("func")    @property    def pp(self):        return 123    @pp.setter    def pp(self,value):        print(value)    @pp.deleter    def pp(self):        print("del")obj = Foo()print(obj.pp) # 执行propertyobj.pp = 999 # 执行setterdel obj.pp # 执行 deletser

 

 

 方法二:property+方法

class Foo:    def f1(self):        return "123"    def f2(self,value):        print(value)    def f3(self):        print("del")    test = property(fget=f1,fset=f2,fdel=f3)obj = Foo()ret = obj.testprint(ret)obj.test = "456"del obj.test

 

Python2.7继承流程

 经典类(当未继承object时):

#深度优先class Bar:    def f1(self):        print("BAR")class A(Bar):    def f(self):        print("A")class B(Bar):    def f1(self):        print("B")class C(A):    def f(self):        print("C")class D(B):    def f1(self):        print("D")class E(C,D):    def f(self):        print("E")obj = E()obj.f1()#E-C-A-Bar

流程图:

 

新式类(继承object时):

#广度优先class Bar(object):    def f1(self):        print("BAR")class A(Bar):    def f(self):        print("A")class B(Bar):    def f(self):        print("B")class C(A):    def f(self):        print("C")class D(B):    def f(self):        print("D")class E(C,D):    def f(self):        print("E")obj = E()obj.f1()#执行流程:E-C-A-D-B-Bar

流程图:

 

抽象方法抽象类:约束

 

#####接口(python里面没有接口)##########用抽象类加抽象方法实现接口#####子类继承抽象类必须至少实现抽象方法的方法==子类中的方法必须等于大于基类中的方法from abc import ABCMetafrom abc import abstractmethodclass Father(metaclass=ABCMeta):    @abstractmethod    def f1(self):pass    @abstractmethod    def f2(self):pass#####继承抽象类和抽象方法class Foo(Father):    def f1(self):pass    def f2(self):pass    def f3(self):passobj = Foo()

转载于:https://www.cnblogs.com/0820-zq/p/5554011.html

你可能感兴趣的文章
关于oracle样例数据库emp、dept、salgrade的mysql脚本复杂查询分析
查看>>
adb shell am 的用法
查看>>
iOS10 UI教程视图和子视图的可见性
查看>>
FindChildControl与FindComponent
查看>>
中国城市json
查看>>
android下载手动下载Android SDK
查看>>
C++学习:任意合法状态下汉诺塔的移动(原创)
查看>>
leetcode133 - Clone Graph - medium
查看>>
UNET学习笔记2 - 高级API(HLAPI)
查看>>
"ORA-00942: 表或视图不存在 "的原因和解决方法[转]
查看>>
Oauth支持的5类 grant_type 及说明
查看>>
C#中用DateTime的ParseExact方法解析日期时间(excel中使用系统默认的日期格式)
查看>>
W3100SM-S 短信猫代码发送 上
查看>>
Log4j知识汇总
查看>>
PHP面向对象(OOP)----分页类
查看>>
监听SD卡状态
查看>>
vs2017 EFCore 迁移数据库命令
查看>>
serialVersionUID的作用
查看>>
liunx trac 插件使用之GanttCalendarPlugin
查看>>
(14)嵌入式软件开发工程师技能要求总结
查看>>