python中类属性不能是对象_python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)...

来源:知乎

致谢:感谢求知教育提供的视频教程

1.单继承

## 封装,继承和多态

## 1.封装

1、满足把内容封装到某个地方,另一个地方去调用封装的内容

2、使用初始化构造方法,或者使用self获取封装的内容

## 2.继承

子类继承父类的属性和内容

1.1单继承示例

class Animal:

def eat(self):

print('吃饭了')

pass

def drink(self):

print('喝水了')

pass

class Dog(Animal):

def wwj(self):

## 子类独有的实现

print('小狗汪汪叫')

pass

class Cat(Animal):

def mmj(self):

## 子类独有的实现

print('小猫喵喵叫')

pass

d1 = Dog()

d1.eat()

d2 = Cat()

d2.eat()

## 总结:所以对于面向对象的继承来说,可以极大的提升效率,减少重复代码

2.多继承

class Shenxian:

def fly(self):

print('神仙会飞')

pass

class Monkey:

def chitao(self):

print('猴子喜欢吃桃')

pass

class Sunwukong(Shenxian,Monkey):

pass

swk = Sunwukong()

swk.fly()

swk.chitao()

2.1 注意方法重名:

## 多个父类存在相同的方法,该调用哪一个

class D(object):

def eat(self):

print('D.eat')

pass

class C(object):

def eat(self):

print('C.eat')

pass

class B(D):

pass

class A(B,C):

pass

a = A()

a.eat

print(A.__mro__) ##显示类的继承顺序

,

,

,

,

## 执行顺序应该是 去A里面查找,找第一个父类,A中没有的话,去B中查找,,B类中没有,C类中没有,去D类中查找;

2.2案例 简洁继承

class Grandfather():

def eat(self):

print('吃的方法')

pass

pass

class Father(Grandfather):

pass

class Son(Father):

pass

son = Son()

print(Son.__mro__)

## ,

## ,

## ,

##

2.3重写父类方法

class Grandfather():

def eat(self):

print('吃的方法')

pass

pass

class Father(Grandfather):

## 覆盖了父类的方法

def eat(self):

print('爸爸经常吃海鲜')

pass

class Son(Father):

pass

son = Son()

print(Son.__mro__)

## 定义跟父类相同的方法,可以实现覆盖和重写父类的方法

2.4重写初始化方法

class Grandfather():

def __init__(self,name):

self.name = name

pass

def eat(self):

print('吃的方法')

pass

pass

class Father(Grandfather):

def __init__(self):

pass

## 覆盖了父类的方法

def eat(self):

print('爸爸经常吃海鲜')

pass

class Son(Father):

pass

son = Son()

print(Son.__mro__)

2.5调用父类初始化方法

class Father:

def __init__(self,name):

self.name = name

pass

## 覆盖了父类的方法

def eat(self):

print('爸爸经常吃海鲜')

pass

class Son(Father):

def __init__(self,name):

Father.__init__(self,name) ##调用父类的方法,可以具备name属性

## 或者

## super.__init__(name) ##也可以这样写

self.age = 90 ## 添加新的实例方法

self.sex = '男'

pass

pass

son = Son('hello')

2.6 调用父类的方法

class Father:

def __init__(self,name):

self.name = name

pass

## 覆盖了父类的方法

def eat(self):

print('父类的吃方法')

pass

class Son(Father):

def __init__(self,name):

Father.__init__(self,name) ##调用父类的方法,可以具备name属性

## 或者

## super.__init__(name) ##也可以这样写

self.age = 90 ## 添加新的实例方法

self.sex = '男'

pass

pass

def __str__(self):

print('{}'.format(self.name))

pass

def eat(self):

super().eat() ##调用父类的方法

print('子类的吃方法')

pass

son = Son('詹躲躲')

son.eat()

## 父类的吃方法

## 子类的吃方法

3 多态

同一种行为,对于不同子类【对象】有不同的实现方式

3.1 要想实现多态,必须有两个前提1.继承:发生在父类和子类之间

2.重写:子类重写父类的方法

3.1 案例演示

class Animal:

## 基本类

def say(self):

print('动物类')

pass

pass

class Duck(Animal):

## 子类 派生类

def say(self):

print('鸭子类')

pass

pass

class Dog(Animal):

## 子类 派生类

def say(self):

print('小狗类')

pass

pass

## duck1 = Duck()

## duck1.say()

## dog = Dog()

## dog.say()

def commonIvoke(obj):

## 统一调用

obj.say()

## 循环统一调用

listObj = [Duck(),Dog()]

for item in listObj:

commonIvoke(item)

## 在定义时的类型跟调用时不一样的时候,称为多态。

3.2 多态的好处

1.增加程序的灵活性

2.增加程序的扩展性

4.类属性和实例属性

## 类属性:就是类对象拥有的属性,它被所有类对象的实例对象所共有,类对象和实例对象可以访问。

## 实例属性:实例对象所拥有的属性,只能通过实例对象访问。

class Student:

## 类属性

name = '叫我詹躲躲'

def __init__(self,age):

self.age = age

pass

pass

lm = Student(18)

## 通过实例对象去访问类属性

print(lm.name)

print(lm.age)

## 通过类对象去访问

print(Student.name)

print(Student.age)

## 总结

## 类属性:类对象和实例对象都可以访问

## 实例属性:只能由实例属性访问

## 所有的实例对象指向同一类对象

## 实例对象去修改类属性 不能修改

## 类对象可以修改类属性 可以修改

5.类属性和静态方法

## 装饰器@classmethod

class Person:

country = 'china'

## 类方法 用classmethod修饰

@classmethod

def get_country(cls):

return cls.country ## 访问类属性

pass

@classmethod

def change_country(cls):

cls.country = 'America'

pass

## 通过类对象去引用

print(Person.get_country())

print(Person.change_country())

print(Person.get_country())

5.1 静态方法

class Person:

country = 'china'

## 类方法 用classmethod修饰

@classmethod

def get_country(cls):

return cls.country ## 访问类属性

pass

@classmethod

def change_country(cls):

cls.country = 'America'

pass

@staticmethod

def get_data():

return Person.country

pass

## 通过类对象去引用

print(Person.get_country())

print(Person.change_country())

print(Person.get_country())

print(Person.get_data())

一般不会通过是实例对象去访问静态方法

由于静态方法主要存放逻辑方法,本身与类以及实例没有交互,也就是不会涉及类中方法和属性的操作

根据资源能够有效的利用

5.2求系统当前的时间

import time

class sys_time:

def __init__(self,hour,min,second):

self.hour = hour

self.min =min

self.second = second

@staticmethod

## 独立的功能

def show_time():

return time.strftime('%H:%M:%S',time.localtime())

print(sys_time.show_time())

## 15:15:44

5.3 总结

1.类方法的第一个参数是类对象,cls进而去引用类对象的属性和方法

2.实例方法的第一个参数是实例属性,若存在相同的实例属性或者方法,实例属性优先级最高

3.静态方法不需要额外的参数,若需要引用属性。,则可以通过类对象或者实例对象去引用即可,必须使用装饰器@staticmethod装饰

6.私有化

6.1 私有化属性

## 私有属性 以__开头,声明为属性私有,不能在类的外部被使用或者直接访问。

class Person(object):

def __init__(self):

self.__name = '叫我詹躲躲' ## 私有化

self.age = '21'

pass

def __str__(self):

return '{}的年龄是{}'.format(self.__name,self.age)

person = Person()

## print(person.__name) ##报错

print(person) ##可以访问

## 叫我詹躲躲的年龄是21

## 私有属性,不能被子类继承

6.2私有化方法

class A(object):

def __eat(self):

print('吃饭')

pass

pass

def run(self):

print('跑步')

pass

pass

b = A()

b.__eat() ## 报错

b.run() ## 跑步

7.property方法

属性函数

class A(object):

def __init__(self):

self.__name = 18

def __eat(self):

return self.__name

pass

pass

def run(self):

print('跑步')

pass

pass

age = property(__eat, run)

b = A()

print(b.age) ## 报错

b.run() ## 跑步

7.1 @age.setter ##修改属性

class A(object):

def __init__(self):

self.__name = 18

def __eat(self):

return self.__name

pass

pass

def run(self):

print('跑步')

pass

@property ##添加属性标识

def age(self):

return self.__name

pass

@age.setter ##修改属性

def age(self,params):

self.age = params

pass

pass

p1 = A()

print(p1.age) ## 18

p1.age = 16

print(p1.age)

8. new方法

作用:创建并返回一个实例对象,如果new只调用了一次,就会得到一个对象。继承自object的新式类,才有new这一魔术方法。

8.1 注意事项

1.__new__是一个实例化调用的第一个方法

2.__new__至少必须有一个参数 cls,代表要实例化的类,此参数在实例化时由python解释器提供,其他的参数是直接传递给__init__方法

3.__new__决定是否使用该__init__方法,因为__new__可以调用其他的类的构造方法或者返回实例对象作为类的实例,如果__new__没有返回实例,则__init__不会被调用

4.在__init__方法中,不能调用自己的__new__方法,return cls__new__(cls),否则会报错。

class A(object):

def __init__(self):

print('__init__执行了')

pass

pass

def __new__(cls,*args,**kwargs):

return super().__new__(cls,*args,**kwargs)

pass

pass

a = A()

print(a)

__init__执行了

<__main__.A object at 0x00000291F97D5160>

## 当__new__返回的时候 __init__才会显示

9.单例模式

9.1 确保一个类只有一个实例存在,使用new

class DataBaseClass(object):

def __new__(cls,*args,**kwargs):

## cls._instance = cls.__new__(cls) ##不能使用自己的new方法

if not hasattr(cls,'_instance'):

cls._instance = super().__new__(cls,*args,**kwargs)

return cls._instance

pass

pass

db1 = DataBaseClass()

db2 = DataBaseClass()

db3 = DataBaseClass()

print(id(db1))

print(id(db2))

print(id(db3))

## 三个指向的内存地址都一样的

## 1852298514784

## 1852298514784

## 1852298514784

10 错误和异常处理

try:

## 可能出现错误的代码块

except:

## 出错之后执行的代码块

else:

## 没有出错的代码块

finally:

## 不管有没有出错,都会执行

10.1 错误和异常处理示例

try:

## 可能出现错误的代码块

li = [1,2,3]

## print(li[10])

print(1/0)

except IndexError as msg:

## 出错之后执行的代码块

print(msg)

except ZeroDivisionError as msg:

## 出错之后执行的代码块

print(msg)

else:

## 没有出错的代码块

print('没有出错了')

finally:

## 不管有没有出错,都会执行

print('出错了')

## 用一个try可以捕获多个不同类型的异常

10.2 使用 Exception处理所有错误

try:

print(b)

except Exception as result:

print(result)

else:

print('出错了')

finally:

print('出错了')

10.3在合适的层次去捕获

def A(s):

return s/int(s)

pass

def B(s):

return A(s)/2

pass

def main():

try:

B(0)

except Exception as result:

print(result)

main()

在合适的位置进行错误捕获

division by zero

10.4 异常运行机制

1、解释器会查找相应的异常捕获类型

2、不断传递给上层,没有找到异常处理,会退出

11.自定义异常类型

class ToolongException(Exception):

def __init__(self, len):

self.len = len

def __str__(self):

return '输入的长度是'+str(self.len)+'长度,超出长度了'

def name_test():

name = input('输入名字')

try:

if len(name)>5:

raise ToolongException(len(name))

else:

print(name)

except ToolongException as result:

print(result)

else:

print('没有出错了')

name_test()

##输入的长度是13长度,超出长度了

12 动态添加属性和方法

import types

class Student:

def __init__(self, name, age):

self.name = name

self.age = age

pass

pass

def __str__(self):

return '{}今天{}岁了'.format(self.name, self.age)

pass

pass

zhz = Student('詹躲躲', 25)

zhz.wight = 60

def dymicMethod(self):

print('{}体重是{}'.format(self.name,self.wight))

pass

## 动态添加属性

print(zhz.wight)

## 类添加属性

Student.pro = '计算机科学'

## 实例可以访问

print(zhz.pro)

## 动态添加实例方法

## import types

zhz.printInfo = types.MethodType(dymicMethod,zhz)

zhz.printInfo()

## 詹躲躲体重是60

13 动态绑定类方法

import types

class Student:

def __init__(self, name, age):

self.name = name

self.age = age

pass

pass

def __str__(self):

return '{}今天{}岁了'.format(self.name, self.age)

pass

pass

zhz = Student('詹躲躲', 25)

zhz.wight = 60

def dymicMethod(self):

print('{}体重是{}'.format(self.name,self.wight))

pass

## 动态绑定类方法

@classmethod

def classTest(cls):

print('类方法')

pass

## 动态绑定静态方法

@staticmethod

def staticTest():

print('静态方法')

pass

13.1.动态添加属性

print(zhz.wight)

13.2.类添加属性

Student.pro = '计算机科学'

## 实例可以访问

print(zhz.pro)

13.3.动态添加实例方法

## import types

zhz.printInfo = types.MethodType(dymicMethod,zhz)

zhz.printInfo()

13.4.动态绑定类方法

Student.testMethod = classTest

Student.testMethod()

13.5.动态绑定类方法 实例调用

zhz.testMethod()

13.6.动态绑定静态方法

Student.statictest = staticTest

Student.statictest()

13.7.动态绑定静态方法 实例调用

zhz.statictest()

14._slots_属性

class Student(object):

__slots__ = ('name', 'age', 'score')

def __str__(self):

return "{},{}".format(self.name, self.age)

xw = Student()

xw.name = '叫我詹躲躲'

xw.age = 25

## print(xw.__dict__)

## {'name': '叫我詹躲躲', 'age': 25}

xw.s11 = '1212'

#### 报错

print(xw)

子类未声明 slots,不会继承父类的slots,此时子类可以随意的属性赋值

子类声明了,范围为 子类+父类的范围

15.题目练习 一

15.1 python new的方法和作用是什么?

用来创建实例对象,只有继承了object的话,才有这个方法。

15.2 什么是单例模式,适用于什么场景?

要求一个类有且只有一个实例,并且提供了全局的访问点。日志插入logger,网站计数器,权限验证模块,window资源管理器,系统回收站,数据库连接池

15.3 私有化方法和私有化属性在子类中能否继承?

不能的

15.4 在python中什么是异常?

程序在执行中出现的异常。

15.5 python中如何处理异常?

分别根据异常的类型去处理

15.6 python中异常处理的一般格式,可以使用伪代码描述?

## try:

## 正常操作

## except:

## ##....

## else:

## ##....

## finally:

## ##...

15.7 slots的作用

限制属性的随意输入,节省内存空间

15.8 私有化的属性的作用?

保护数据,封装性的体现

15.9 在类外是否修改私有属性?

不可以直接修改,通过方法去实现,可以借助property

15.10 如果一个类,只有指定的属性或者方法能被外部修改,该如何限制?

对属性进行私有化

16 题目练习二

16.1 定义一个person类,类中要有初始化方法,方法中要有人名,年龄两个私有属性

提供获取用户信息的函数,提供设置私有属性的方法,设置年龄在0-120岁中间,如果不在这个范围,不能设置成功

class Person:

def __init__(self,name,age):

self.__name = name

self.__age = age

pass

pass

def GetUserInfo(self):

return "{}的年龄为{}".format(self.__name,self.__age)

pass

pass

def __str__(self):

return "{}的年龄为{}".format(self.__name,self.__age)

def setAge(self,age):

if age>0 and age<120:

self.__age = age

else:

pass

person = Person('詹躲躲',19)

print(person.GetUserInfo())

## 詹躲躲的年龄为19

print(person.setAge(30))

print(person.GetUserInfo())

## 詹躲躲的年龄为30

16.2 请写一个单例模式

class DataBaseClass(object):

def __new__(cls,*args,**kwargs):

## cls._instance = cls.__new__(cls) ##不能使用自己的new方法

if not hasattr(cls,'_instance'):

cls._instance = super().__new__(cls,*args,**kwargs)

return cls._instance

pass

pass

db1 = DataBaseClass()

db2 = DataBaseClass()

db3 = DataBaseClass()

print(id(db1))

print(id(db2))

print(id(db3))

16.3 创建一个类,并定义两个私有化属性,提供一个获取属性的方法。利用property属性给调用者提供调用

class Student:

def __init__(self, name, score):

self.__name = name

self.___score = score

@property

def name(self):

return self.__name

@name.setter

def name(self, name):

self.__name = name

def __str__(self):

return self

def __call__(self, *args, **kwargs):

print(self.name)

pass

pass

xm = Student('詹躲躲',98)

xm.__call__()

xm.name()

16.4 创建一个Animal类。实例一个cat对象,给cat 绑定一个run方法,给类绑定一个类属性color

import types

class Animal:

pass

def run(self):

print('小猫')

cat = Animal()

cat.run = types.MethodType(run,cat)

cat.run()

Animal.color = 'red'

print(cat.color)

def info():

print('ok')

Animal.info = info

Animal.info()

来源:知乎

致谢:感谢求知教育提供的视频教程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值