目录
3.9 面向对象下
3.9.1 私有化属性
-
语法
-
两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问
-
class Person(object):
__age = 18 #定义一个私有化属性,属性名字前面加两个下划线
使用私有属性的场景
1.把特定的属性隐藏起来,不想让类的外部进行直接调用。
2.保护不让属性的值随意改变。
3.保护属性不被派生类(子类)去继承。
class Person(object):
def __init__(self):
self.name = "Rany"
self.__age = 18 #定义一个私有化实例属性,属性名字前面加两个下划线
pass
def __str__(self):
return "{}的年龄是{}".format(self.name,self.__age) #私有化属性可以在内部使用
def ChangeValue(self):
Person.__age = 19 # 修改私有化属性的值
one = Person()
print(one)
#print(one.age) #运行私有化属性,私有化之后,不能在外部进行访问。
-
私有化属性只能在定义类中进行访问和使用
-
子类不能继承父类的私有化属性只能继承公共的属性和行为
3.9.2 私有化方法
-
概述:
-
私有化方法和私有化属性概念一样,有些重要的方法,不允许被外部调用,防止子类意外重写,把普通的方法设置成私有化方法
-
-
语法:
-
私有化方法,即在方法名前加两个下划线
-
class Animal:
def __eat(self): #定义一个私有化方法
print("吃蛋糕")
pass
def drink(self):
print("喝可乐")
pass
pass
class Dog(Animal):
pass
one = Dog()
one.drink()
-
私有化方法一般是类内部调用,子类不能继承,外部不能调用
-
单下划线、双下划线、头尾双下划线说明
-
_XXX前面加一个下户线,以单下划线开头是保护类型,只能允许其本身于子类进行访问。
-
XXX前后下户线是魔术方法,一般是python自有,开发者不要创建这种类型的方法。
-
XXX_后面下划线,避免属性名与python关键字冲突。
-
3.9.3 Property属性函数
通过属性的形式去访问我们已经私有化的方法喝
-
方法一
class Person(object):
def __init__(self):
self.__age = 19 #定义一个私有化属性,属性名字前面加__下划线
pass
def get_age(self): #访问私有实例属性
return self.__age
def set_age(self,age): #修改私有实例属性
if age < 0:
print("年龄不能小于0")
pass
else:
self.__age = age
pass
pass
age = property(get_age,set_age) #定义一个属性,当对这个age设置值时调用set__age,
#当获取值时调用get__age
#注意:必须是以get和set开头的方法才能被调用
pass
pi = Person()
print(pi.age)
pi.age=20
print(pi.age)
-
方法二 在方法上使用装饰器
class Person(object):
def __init__(self):
self.__age = 19 #定义一个私有化属性,属性名字前面加__下划线
pass
@property #使用装饰器对age进行修饰,提供一个getter方法
def age(self): #访问私有实例属性
return self.__age
@age.setter #使用装饰器进行装饰,提供一个setter方法
def age(self,age): #修改私有实例属性
if age < 0:
print("年龄不能小于0")
pass
else:
self.__age = age
pass
pass
pass
pi = Person()
print(pi.age)
pi.age = 20
print(pi.age)
3.9.4__new__
方法
-
__new__
方法的作用是,创建并返回一个实例对象,如果__new__
只调用了一i此,就会得到一个对象。继承自object的新式类才有new这一魔术方法。
-
注意
-
__new__
是在一个对象实例化的时候调用的第一个方法 -
__new__
至少必须要有一个参数cls,代表要实例化的类,此参数在实例化时由python解释器提供,其他的参数是用来直接传递给__init__
方法 -
__new__
决定是否要使用__init__
方法,因为__new__
可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果__new__
没有返回实例对象,则__init__
不会被调用 -
在
__new__
方法中,不能调用自己的__new__
方法,即:return cls.__new__
(cls),否则会报错超过最大递归深度
-
class A:
def __init__(self):
print("__init__执行了")
pass
#在python当中,如果不重写__new__默认结构如下
def __new__(cls, *args, **kwargs):
print("__new__执行了")
return object.__new__(cls)
pass
a = A() #实例化的过程会自动调用__new__去创建实例
3.9.4.1 单例模式
作用:确保一个系统只有一个类的实例存在
#创建一个单例对象,基于__new__去实现的
class DateBaseClass:
def __new__(cls, *args, **kwargs):
if not hasattr(cls,"_instance"): #如果不存在就开始创建
cls._instance = super().__new__(cls,*args,**kwargs)
return cls._instance
pass
pass
class OBoptions(DateBaseClass): #子类继承父类来查看是否为同一个
pass
db1=DateBaseClass()
print(id(db1)) #通过内存地址查看是否为一个对象
db2=DateBaseClass()
print(id(db2))
3.9.5 错误与异常处理
-
执行程序时,我们难免会执行错误代码,程序直接终止报错,这是因为python检测到一个错误时,解释器就无法继续执行了,出现了错误的提示,这就是异常。
语法格式
try:
可能出现错误的代码块
except:
出错之后执行的代码块
else:
没有出错的代码块
finally
不管有没有出错都要执行的代码块
举例
try:
#print(Rany)
lis = [1,2,8]
print(lis[5])
pass
except NameError as msg: #捕捉命名的错误
# 捕获到的错误,在这里来执行
print(msg)
pass
except IndexError as msg: #可以捕获索引类型的错误
print(msg)
print("错误后依然可以正常执行以下代码")
-
except 在捕获错误异常的时候,需要根据具体的错误类型来捕获的
try:
# print(Rany)
lis = [1,2,8]
print(lis[5]) # 无内容
pass
except Exception as msg: # 万精油错误类型捕获
print(msg)
pass
print("错误后依然可以正常执行以下代码")
-
当出现的问题不确定时,可以使用Exception异常
try:
print(Rany)
#print("Rany")
pass
except Exception as msg: # 万精油错误类型捕获
print(msg)
else:
print("出错不执行,不出错执行")
finally:
print("不管有没有出错都要执行的代码")
-
自定义异常:间接或直接继承Error或者Exception类
-
由开发者主动抛出自定义异常,在Python中使用raise关键字
3.9.6 动态添加属性和方法
-
动态语言:运行时可以改变其结构的语言,例如新的函数、对象、甚至代码可以呗引进,已有的函数可以被删除或是其他结构上的变化。
-
Python可以在程序运行过程中添加属性和方法。
import types
class Empoyee:
def __init__(self,name,age):
self.name = name
self.age = age
pass
def __str__(self):
return "{}已经{}岁了".format(self.name,self.age)
pass
Rany = Empoyee("Rany",19)
Rany.weight = 75 # 动态添加
print(Rany)
print(Rany.weight)
# 给类对象添加属性
Empoyee.school = "svu"
print(Rany.school)
# 动态添加实例方法
emmmm,我觉得这块很鸡肋,大概了解就行了,知道可以这么做就好了,没必要过多了解,如果以后用到,再去了解也不迟。不过我觉得我很难用得到。