Python之路【第6天】
来源:互联网 发布:skycc营销软件客服 编辑:程序博客网 时间:2024/05/13 05:02
目录
- 深入面向对象
- 类的成员
2.1字段
2.1方法
2.3属性 - 类成员的修饰符
3.1公有成员
3.2私有成员 - 类的特殊成员
- 异常处理
- 反射
深入面向对象
- 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
- 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)
- 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
- 面向对象三大特性:封装、继承和多态
类的成员
类的成员可以分为三大类:字段、方法和属性
一、字段
字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,
•普通字段属于对象
•静态字段属于类
class Province: country="中国" #静态字段 def __init__(self,name): self.name=name #普通字段obj=Province("河北省")print(obj.name) # 直接访问普通字段print(Province.country) # 直接访问静态字段
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
二、方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
•普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
•类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
•静态方法:由类调用;无默认参数;
class Foo: def __init__(self,name): self.name=name def ord_func(self): #定义普通方法,至少一个self参数 print("普通方法") @classmethod def class_fun(cls): #定义类方法,至少有一个cls参数 print("类方法") @staticmethod def static_func(): #定义静态方法,无默认参数 print("静态方法")#调用普通方法f=Foo("aa") #先实例化一个对象f.ord_func()#调用类方法Foo.class_fun()#调用静态方法Foo.static_func()
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
三、属性
如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种。
对于属性,有以下三个知识点:
•属性的基本使用
•属性的两种定义方式
1、属性的基本使用
class Foo: def func(self): print("调用了方法") pass @property #定义属性 def prop(self): print("prop方法") passobj=Foo() #实例化obj.func() #调用func方法obj.prop #调用属性,无需加括号
由属性的定义和调用要注意一下几点:
•定义时,在普通方法的基础上添加 @property 装饰器;
•定义时,属性仅有一个self参数
•调用时,无需括号
方法:obj.func()
属性:obj.prop
注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
2、属性的两种定义方式
属性的定义有两种方式:
•装饰器 即:在方法上应用装饰器
•静态字段 即:在类中定义值为property对象的静态字段
装饰器方式:在类的普通方法上应用@property装饰器
我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )
经典类,具有一种@property装饰器
class Goods: @property #定义属性 def price(self): return "1000"obj=Goods() #实例化print(obj.price) #调用属性
新式类,具有三种@property装饰器
class Goods(object): @property #定义属性 def price(self): print("@property") @price.setter #可以设置属性赋值 def price(self,value): self.value=value print("@price.setter[%s]"%self.value) @price.deleter #可以执行删除操作 def price(self): print("@price.deleter ")obj=Goods()obj.price #调用price方法obj.price=123 #调用price方法,将 123赋值给方法的参数del obj.price#结果为:@property@price.setter[123]@price.deleter
注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
class Goods(object): def __init__(self): self.original_price=100 self.discount=0.8 def get_price(self): new_price=self.original_price*self.discount return new_price def set_price(self,value): self.original_price=value def del_price(self,value): del self.original_price #分别将三个方法定义为对同一个属性:获取、修改、删除 price=property(get_price,set_price,del_price,"价格属性描述")obj=Goods()print(obj.price) # 获取商品价格obj.price=200 # 修改商品原价print(obj.price)#del obj.price # 删除商品原价
类成员的修饰符
每一个类的成员而言都有两种形式:
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:init、call、dict等)
class C: def __init__(self): self.name="public" self.__foo="private"
私有成员和公有成员的访问限制不同:
静态字段
公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
私有静态字段:仅类内部可以访问;
class C: name="公有静态字段" def func(self): print(C.name)class D(C): def show(self): print(C.name)C.name #类访问obj=C() #实例化obj.func() #类内部可以访问sub_obj=D() #实例化sub_obj.show() #派生类中可以访问#结果为:公有静态字段公有静态字段
私有静态字段
class C: __name="公有静态字段" def func(self): print(C.__name)class D(C): def show(self): print(C.__name)#C.__name #类访问 ==>提示没有个属性,访问不了obj=C() #实例化obj.func() #内部访问 ==>正常访问sub_obj=D() #实例化sub_obj.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 #通过对象访问 ==> 可以访问#print(obj.foo)obj.func() #类内部访问 ==>可以访问obj_sub=D() #实例化obj_sub.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_sub=D() #实例化obj_sub.show() #派生类访问 ==>提示无法访问
方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用
类的特殊成员
Python的类成员以及成员修饰符,从而了解到类中有字段、方法和属性三大类成员,并且成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。无论人或事物往往都有不按套路出牌的情况,Python的类成员也是如此,存在着一些具有特殊含义的成员,详情如下:
- doc
表示类的描述信息
class Foo: """描述类信息,这里会被显示""" def func(self): passprint (Foo.__doc__)#结果为:描述类信息,这里会被显示
- module 和 class
module 表示当前操作的对象在那个模块
class 表示当前操作的对象的类是什么
__main__<class '__main__.C'>#结果为:__main__<class '__main__.C'>
3 call
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
4 dict
获取类的成员,即:静态字段、方法、
5 str
如果一个类中定义了str方法,那么在打印 对象 时,默认输出该方法的返回值。
class Foo: def __str__(self): return "aa"obj=Foo()print (obj) #打印得到的返回值print(Foo.__dict__) # 获取类的成员#结果为:aa{'__module__': '__main__', '__str__': <function Foo.__str__ at 0x00000198EAC52620>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
6 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"]="aa" #自动触发执行 __setitem__del obj["k1"] #自动触发执行 __delitem__
7 getslice、setslice、delslice
该三个方法用于分片操作,如:列表
异常处理
1、异常基础
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面
需求:将用户输入的两个数字相加
while True: num1=input("num1:") num2=input("num2:") try: num1=int(num1) num2=num2 #故意不将字符串转化为数字型 ret=num1+num2 break except Exception: print("出现异常,信息如下:") breakprint (ret)#结果为:num1:1num2:2出现异常,信息如下:
2、异常种类
- python中的异常种类非常多,每个异常专门用于处理某一项异常!!!
- AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
- IOError 输入/输出异常;基本上是无法打开文件
- ImportError 无法引入模块或包;基本上是路径问题或名称错误
- IndentationError 语法错误(的子类) ;代码没有正确对齐
- IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
- KeyError 试图访问字典里不存在的键
- KeyboardInterrupt Ctrl+C被按下
- NameError 使用一个还未被赋予对象的变量
- SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
- TypeError 传入对象类型与要求的不符合
- UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
- ValueError 传入一个调用者不期望的值,即使值的类型是正确的
ArithmeticErrorAssertionErrorAttributeErrorBaseExceptionBufferErrorBytesWarningDeprecationWarningEnvironmentErrorEOFErrorExceptionFloatingPointErrorFutureWarningGeneratorExitImportErrorImportWarningIndentationErrorIndexErrorIOErrorKeyboardInterruptKeyErrorLookupErrorMemoryErrorNameErrorNotImplementedErrorOSErrorOverflowErrorPendingDeprecationWarningReferenceErrorRuntimeErrorRuntimeWarningStandardErrorStopIterationSyntaxErrorSyntaxWarningSystemErrorSystemExitTabErrorTypeErrorUnboundLocalErrorUnicodeDecodeErrorUnicodeEncodeErrorUnicodeErrorUnicodeTranslateErrorUnicodeWarningUserWarningValueErrorWarningZeroDivisionError
s1="hello"try: int(s1)except KeyError: print("键错误")except IndexError: print("索引错误")except TypeError: print("类型错误")except Exception: print("出现了错误")
主动触发异常
try: raise Exception('错误了。。。')except Exception: print("出现了错误")
自定义异常
class UserException(Exception): def __init__(self,msg): self.message=msg def __str__(self): return self.messagetry: raise UserException("自定义异常")except UserException: print("出现了错误")
反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
class Foo(object): def __init__(self): self.name="aa" def func(self): return "func"obj=Foo()# #### 检查是否含有成员 ####print(hasattr(obj,"name"))print(hasattr(obj,"func"))# #### 获取成员 ####getattr(obj,"name")getattr(obj,"func")# #### 设置成员 ####setattr(obj,"age",18)setattr(obj,"show",lambda num:num+1)print(obj.age)print(obj.show(obj.age))# #### 删除成员 ####delattr(obj,"name")#delattr(obj,"func")#结果为:TrueTrue1819
结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!
- Python之路【第6天】
- Python之路【第1天】
- Python之路【第2天】
- Python之路【第3天】
- Python之路【第4天】
- Python之路【第5天】
- Python学习之路-第一天
- Python基础教程之第6章 抽象
- python之路-------第4章、介绍python对象类型
- Python之路【第一篇】:Python简介和入门
- Python 第一天之问题
- 坚持#第230天~零基础自学云计算基础语言应用之python第6节
- Python 第一天之Python环境配置
- python第4天:基本类型之序列
- python之路-------第3章、如何运行程序,热身
- Python Manual读书笔记之第6章动态类型简介
- 第6课时:python之常用操作符
- python 第2天
- Linux~常用的命令
- Vero Radan 2018 R1(钣金设计软件)官方版下载附安装教程
- 目标跟踪之LK光流法
- ElasticSearch 单机部署多实例环境
- c++中冒号(:)和双冒号(::)的用法
- Python之路【第6天】
- 三部排序
- C#操作Excel
- 字节流之文件输入流FileInputStream(下)
- 用Scala语言实现冒泡排序
- elasticsearch基本搜索
- 谈谈程序员的离职和跳槽
- 程序员偷偷深爱的9个不良编程习惯
- 灵活的 overflow