Python#Day9

面向对象(下)

1.私有化属性
2.私有化方法
3.Property属性
4.__new__方法
5.单例模式
6.错误与异常处理
7.Python动态添加属性和方法
8.__slots__属性

私有化属性

作用
①防止他人随意修改或意外修改
②把特定的一个属性隐藏起来,不想让类的外部进行直接调用
③不想让派生类【子类】去继承
语法
定义一个私有化属性,属性名字前面加两个下划线

class Person(object):
	__age=18 #定义一个私有化属性,属性名字前面加两个下划线

例子——外部无法访问

class Person:
    def __init__(self):
        self.__name='李四' #将两个下划线 将属性私有化
        self.__age=30
        pass
    pass

x1=Person()
print(x1.name) #通过类对象 在外部访问

>>>Traceback (most recent call last):
>>>  File "E:/python/python_study/Day9/私有化属性.py", line 9, in <module>
>>>    print(x1.name)
>>>AttributeError: 'Person' object has no attribute 'name'

类的内部访问例子

class Person:
    def __init__(self):
        self.__name='李四' #将两个下划线 将属性私有化
        self.__age=30
        pass
    def __str__(self):
       return '{}的年龄是{}'.format(self.__name,self.__age) #内部访问
    pass
x1=Person()
print(x1)

总结
私有化的【实例】属性,不能再外部直接的访问,可以再类的内部随意的使用。
==ps.==类内部可以修改私有化属性

class Person:
    __hobby='跳舞'
    def __init__(self):
        self.__name='李四' #将两个下划线 将属性私有化
        self.__age=30
        pass
    def __str__(self):
        return '{}的年龄是{} 爱好是{}'.format(self.__name,self.__age,Person.__hobby)
    def changeValue(self):
        Person.__hobby='张三'
    pass
x1=Person()
print(x1)
print('-------------修改后---------------')
x1.changeValue()
print(x1)
>>>李四的年龄是30 爱好是跳舞
>>>------------修改后---------------
>>>李四的年龄是30 爱好是张三

私有化方法

作用
私有化方法一般是类内部调用,子类不能继承,外部不能调用

区分:左单边下划线,双边下划线,右单边下划线
①_xxx: 私有化(保护)
②_xxx_ :魔术方法,python的内置方法
③xxx_
: 避免属性名与python冲突,不具备特殊特点

语法
定义一个私有化方法,属性名字前面加两个下划线

class Person(object):
	__def eat(self):
		  print('吃东西')
		  pass

类的内部可以调用方法
例子

class Animal:
    def __eat(self):
        print('吃东西')
        pass
    def run(self):
        self.__eat()
        print('飞快的跑')
        pass
    pass

class Bird(Animal):
    pass

b1=Bird()
b1.run()
>>>吃东西
>>>飞快的跑

Property

作用:访问私有化的属性或方法

①property方法设置
语法

class:
	def ...
	property(可调用的方法)

实例

class Person(object):
    def __init__(self):
        self.__age=18
        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) #注意:必须是以get,set开头的方法名,才能被调用  
    pass

p1=Person()
print(p1.age)
print('-----------修改后------------')
p1.age=25
print(p1.age)
# p1.get_age()
>>>18
>>>-----------修改后------------
>>>25

ps. age=property(get_age,set_age) 中的age只是一个赋值句,可以用其他XXX代替,但是对应的调用时也要用对用的XXX

②用装饰器

语法

class():
	def __init__(self):
		....
	@property #添加装饰器
	def xxx
	@xxx.setter #设置修改
class Person(object):
    def __init__(self):
        self.__age=18
        pass
    @property
    def age(self):
        return self.__age
    @age.setter #提供参数设置的方法
    def age(self,parms):
        if parms < 0:
            print('年龄不能小于0')
            pass
        else:
            self.__age=parms
            pass
        pass
    pass

p1=Person()
print(p1.age)
print('-------------修改--------------')
p1.age=30
print(p1.age)

__new__方法

__new__是新式类中出现,是一种静态方法。
语法

def __new__(cls,*args,**kwargs):
	return object.__new__(cls,*args,**kwargs)
	pass

1.__new____init__区别

__new____init__的主要区别在于:__new__是用来创造一个类的实例的(constructor),而__init__是用来初始化一个实例的(initializer)。

2.__new____init__参数的不同

__new__所接收的第一个参数是cls,而__init__所接收的第一个参数是self。这是因为当我们调用__new__的时候,该类的实例还并不存在(也就是self所引用的对象还不存在),所以需要接收一个类作为参数,从而产生一个实例。而当我们调用__init__的时候,实例已经存在,因此__init__接受self作为第一个参数并对该实例进行必要的初始化操作。这也意味着__init__是在__new__之后被调用的。

3.__init__不可返回

如果我们在__init__中加上return语句,将会导致TypeError: __init__() should return None的错误。

class oldStyleClass:
    def __init__(self):
        return 29

oldStyleClass()
>>>TypeError: __init__() should return None

4.__new__的调用

①这里需要注意的是,如果__new__函数返回一个已经存在的实例(不论是哪个类的),__init__不会被调用。
②如果我们在__new__函数中不返回任何对象,则__init__函数也不会被调用
③只有在__new__返回一个新创建属于该类的实例时当前类的__init__才会被调用。

ps.
① __new__是一个对象实例化时候所调用的第一个方法
②__new__必须要有一个参数cls,代表实例化的类,此参数在实例化时由Python解释器自动提供,其他蚕食时用来直接传递给__init__方法
③__new__决定是否使用__init__方法,因为__new__可以调用其他类的构造方法或者直接返回别的实例对象作为本类的实例,如果__new__没有返回实例对象,则__init__不会被调用
④在__new__方法中,不能调用自己的__new__方法,即:return cls._new_(cls),否则会报错(RecursionError: maximum recursion depthn exceeded: 超过最大递归深度)

单例模式

常用的软件设计模式,能确保一个类只有一个实例存在,并且提供了一个全局的访问点,类似于window上的回收站。

class DataBaseClass(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            cls._instance=super().__new__(cls,*args,**kwargs)
        return cls._instance
        #切忌不能使用自身的new方法,如cls.__instance=cls.__new__(cls)
    pass

db1=DataBaseClass()
print(id(db1))
db2=DataBaseClass()
print(id(db2))
db3=DataBaseClass()
print(id(db3))

Python错误处理

try——except

作用
①捕获指定的错误类型,并反馈,但不会影响后续代码的执行——示例1
②一个try可以跟着多个except
③exception 可以捕获所有异常(当对错误异常不确定时)——示例2

示例1

try:
	print(b)
	pass
except NameError as msg:
	print(msg)
	pass
print('1111111111')
>>>name 'b' is not defined
>>>1111111111

示例2

try:
	print(b)
	pass
except Exception as result: #捕获所有错误并返回信息
	print(result)
	pass
print('1111111111')
>>>name 'b' is not defined
>>>1111111111

try—except—else

else:下的语句在没有错误时运行

try-except-finally

finally:不管有没有出错都执行的代码块。

自定义异常

通过直接或间接继承Error或Exception类,并与raise组合
多训练代码

动态添加属性

1.通过实例添加属性,但是只有对应实例才能访问

class Student:
	def __init__(self,name,age):
	 	self.name=name
	 	self.age=age
	 	pass
	 pass
cat = Student('小明',30)
#动态添加color属性——通过实例
cat.color = '白色'
print(cat.color)

2.通过类对象添加属性,任何实例对象都可以访问

class Student:
	def __init__(self,name,age):
	 	self.name=name
	 	self.age=age
	 	pass
	 pass
cat = Student('小明',30)
#动态添加color属性——通过实例
Student.color = '白色'
print(cat.color)

动态添加方法

1.绑定实例方法

利用import types #添加方法的库——仅针对实例方法

def dymicMethod:
	return ...

xxx.printinfo=types.MethodType(dymicMethod,xxx)
xxx.printinfo()

2.绑定方法

@classmethod

@classmethod
def classTest(cls):
	print('这是一个类方法')
	pass
Student.TestMethod=classTest

3.绑定静态方法

@staticmethod

@staticmethod
def staticMethodTest():
	print('这是一个静态方法')
	pass
Student.staticMethodTest=staticMethodTest

__slots__属性限制

作用:限制该class的实例能添加的属性
只有在__slots__变量中的属性才能被添加,没有在__slots__变量中的属性会添加失败。可以防止其他人在调用类的时候胡乱添加属性或方法。
==ps.==在未定义__slots__后,类的实例不再存储在__dict__,而是存储在__slots__中,可以节省内存空间

语法

class A(object):
	__slots__=('属性1','属性2')

在设定了__slots__后无法添加__slots__之外的属性,比如gender,如下例所示:

class Student(object):
    __slots__ = ('name','age')
    def __str__(self):
        return '姓名{} 年龄{} 性别{}'.format(self.name,self.age,self.gender)
    pass
xw=Student()
xw.name='小王'
xw.age=30
xw.gender='男' 
print(xw)

结果

Traceback (most recent call last):
  File "E:/python/python_study/Day9/__slots__.py", line 10, in <module>
    xw.gender='男'
AttributeError: 'Student' object has no attribute 'gender'

__slots__属性子类不会继承,只能在当前类中生效。如果子类中也添加__slots__,不用声明具体的属性,可以继承父类限制的属性**(如果在子类的__slots__中重复声明父类中的属性,则会占用多余的内存空间,时没有必要的)**,但同样的,如果子类中的__slots__声明了新的属性,则在子类中可以添加新的属性

class Student(object):
    __slots__ = ('name','age')
    def __str__(self):
        return '姓名{} 年龄{}'.format(self.name,self.age)
    pass
class subStudent(Student):
    __slots__ = ('pro')
    def __str__(self):
        print('{}...{}...'.format(self.name,self.pro))
        pass
    pass
ln=subStudent()
ln.name='临安'
ln.pro='环境科学'
print(ln.name,ln.pro)

课后作业
1.Python中new方法作用是什么?
用来创建实例对象,只有以objec为基类 才能有这个方法

2.什么是单例模式?
要求一个类有且只有一个实例,并且提供一个全局的访问点

3.私有化方法与私有化属性在子类中能否继承?
不能继承

4.在Python中什么是异常?
程序在执行的过程中发生的错误

5.Python如何处理异常?
根据类型设定异常捕获分类。

6.Python 中异常处理语句的一般格式。
try:

except:

else:

finally:

7.__slots__属性的作用
①限制属性的随意输入
②节省内存空间
8.私有化属性的作用
保护数据
9.在类外面是否能修改私有属性
不可以直接修改,要通过方法去实现,还可以借助属性函数property去实现
10.如果一个类中,只有指定的属性或这方法能被外部修改,那么如何限制外部修改
通过设定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值