python3.x 基础七:面向对象进阶

Posted jenvid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python3.x 基础七:面向对象进阶相关的知识,希望对你有一定的参考价值。

类的高级方法:

1.静态方法:在类方法前增加关键字@staticmethod,将普通方法变成静态方法,不能再次传值,不能访问实例变量或者类变量,与类的关系仅仅是通过类名进行调用

2.类方法:在类方法前增加关键字@classmethod,类方法只能访问类变量,不能访问实例变量

3.属性方法:(重点)在类方法前增加关键字@property,调用的时候通过属性一样的方式访问(去掉括号调用),可以通过类私有属性加@setter重新赋值,@deleter删除私有属性后方能删除属性方法

  • 静态方法:
class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
obj1=Dog(hashiqi)
obj1.eat(baozi)

正常输出:hashiqi is eating baozi

增加关键字staticmethod:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @staticmethod
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
obj1=Dog(hashiqi)
obj1.eat(baozi)

报错:

Traceback (most recent call last):
  File "D:/001python/01course/day07/static_method.py", line 11, in <module>
    obj1.eat(baozi)
TypeError: eat() missing 1 required positional argument: food

eat的实参没有传给self

结论:增加关键字@staticmethod后,类的方法变成了单纯的函数,无法访问类或者实例中的任何属性,仅增加类名进行调用

如果非要给静态方法传类属性,可以直接将对象传进去---没有意义:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @staticmethod
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat(obj1)

输出:hashiqi is eating 

  • 类方法  --关键字@classmethod

类方法无法访问实例属性

class Dog(object):
    #name=‘yzw‘
    def __init__(self,name):
        self.name=name
    @classmethod
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat()

报错如下:

    print(%s is eating %(self.name))
AttributeError: type object Dog has no attribute name

类方法只能访问类属性:

class Dog(object):
    name=yzw
    def __init__(self,name):
        self.name=name
    @classmethod
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat()

输入:yzw is eating 

  • 属性方法--关键字@property

无法正常使用调用方法

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat()

报错如下:

    obj1.eat()
TypeError: NoneType object is not callable

改成调用属性的方法,也就是把括号去掉:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat

正常输出:hashiqi is eating 

结论:把一个方法变成一个静态属性,无法通过()进行调用,它可以通过"对象.属性"进行调用

属性普通赋值也会报错:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=value

error:
    obj1.eat=value
AttributeError: cant set attribute

结论:属性方法可以通过属性调用方式获取,但是不能直接给予赋值

通过特殊处理给属性方法传值:

再写一个同名的方法,使用@xxx.setter关键字进行赋值,但是怎么才能给属性里面的形参传值呢?

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
    @eat.setter
    def eat(self,food):
        print(food)
obj1=Dog(hashiqi)  #正常实例化对象
obj1.eat  # 调用属性方法
obj1.eat=value‘  #调用属性赋值方法

hashiqi is eating 
value

属性传值二:

通过在构造方法里增加私有属性,给属性方法其他形参传值

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating%self.name,self.__food)
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
d=Dog(hashiqi) # 1.正常实例化对象
d.eat   # 2.正常调用属性方法  输出:hashiqi is eating None,此时self.__food的值取构造方法的初始值
d.eat=包子  # 3.通过setter属性赋值方法给方法赋值
d.eat   # 4.再次调用属性方法,输出属性方法的结果,此时属性方法调用setter里设置的值

hashiqi is eating None 
baozi
hashiqi is eating baozi 

 

删除属性方法--无法删除:

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating %s %(self.name,self.__food))
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=baozi
obj1.eat
del obj1.eat

error
AttributeError: cant delete attribute

删除属性方法--先删除私有属性

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating %s %(self.name,self.__food))
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
    @eat.deleter
    def eat(self):
        del self.__food
        print(had been deleted)
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=baozi
obj1.eat
del obj1.eat

hashiqi is eating None 
baozi
hashiqi is eating baozi 
had been deleted

删除再进行调用报错:

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating %s %(self.name,self.__food))
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
    @eat.deleter
    def eat(self):
        del self.__food
        print(had been deleted)
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=baozi
obj1.eat
del obj1.eat
obj1.eat  # 依然是去调用静态方法,此时私有属性已被删除

error
    print(%s is eating %s %(self.name,self.__food))
AttributeError: Dog object has no attribute _Dog__food

 属性方法用途:隐藏细节,暴露简单接口给用户

案例:查询航空班次状态

1.调用航空公司API查询

2.对查询结果进行分析

3.将分析后的结果返回页面,用户不关心过程/方法,只关心状态,也就是属性方法的结果

class Flight(object):
    def __init__(self,name):
        self.fly_name=name
    def checking_status(self):
        print(checking flight %s status...%self.fly_name)
        return 3
    @property
    def Flight_status(self):
        status=self.checking_status()
        if status == 0:
            print(flight had got canceled)
        if status == 1:
            print(flight is arrived)
        if status == 2:
            print(flight has departured already...)
        if status == 3:
            print(cannot confirm the flight status ... check later pls)
    @Flight_status.setter
    def Flight_status(self,status):
        status_dict={0:canceled,1:arrived,2:"departured"}
        print(status has changed to %s%status_dict.get(status))
fly1=Flight(A380)
fly1.Flight_status
fly1.Flight_status = 1

output:
checking flight A380 status...
cannot confirm the flight status ... check later pls
status has changed to arrived

 类的特殊成员方法

1.__doc__ 打印类下面的注释信息

class Class_name(object):
    ‘‘‘class description‘‘‘
    pass
print(Class_name.__doc__)

output:class description

2.__module__ 打印模块的名字    __class__ 打印类的名字

from fly import Flight
t=Flight(A380)
print(t.__module__)
print(t.__class__)

output:
status has changed to arrived
fly
<class fly.Flight>

3.__init__  构造方法,实例化类的时候自动创建

4.__del__ 析构方法,一般不定义,系统会自动执行回收垃圾

5.__call__ 对象后面加括号,触发执行

class Dog(object):
    def __init__(self):
        pass
    def __call__(self, *args, **kwargs):
        print(*args,**kwargs)
d1=Dog()
d1(1,2,3)

output:
1 2 3

6.__dict__ 打印字典形式的类属性方法或者实例属性

class Dog(object):
    address=earth
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def func1(self, *args, **kwargs):
        print(*args,**kwargs)
print(Dog.__dict__)  #以字典形式打印类的所有属性和方法
d1=Dog(hashiqi,19)
print(d1.__dict__)  #以字典形式打印实例的属性

7.__str__ 如果一个勒种定义了__str__方法,那么打印对象的时候,默认输出该方法的返回值

class Dog(object):
    address=earth
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def func1(self, *args, **kwargs):
        print(*args,**kwargs)
    def __str__(self):  # 如果没有定义str方法,将打印对象的内存地址
        return (return value)

d1=Dog(hashiqi,19)
print(d1)

output:return value

8. item字典方法,使用起来像操纵字典,其实是类内置方法

class Dog(object):
    def __getitem__(self, item):
        print(getitem,item)
    def __setitem__(self, key, value):
        print(setitem,key,value)
    def __delitem__(self, key):
        print(delitem,key)
d1=Dog()  # 1.实例化对象
value1=d1[key1] # 2.调用getitem方法
d1[key2]=value2  # 3.调用setitem方法
del d1[key3]  # 4.调用delitem方法

output:
getitem key1
setitem key2 value2
delitem key3

类的本质

反射

  • hasattr(obj,name_str) 判断一个对象里是否有对应的字符串方法
  • getattr(obj,name_str)根据字符串去获取obj对象里对应的方法的内存地址
  • setattr(obj,‘y‘,z) 相当于与obj.y=z
  • delattr
class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self):
        print(%s is eating...%self.name)

d1=Dog(hashiqi)
choice =input(input>>).strip()

#判断有没有方法
print(hasattr(d1,choice)) #判断输入的字符串在内存地址中是否存在
print(getattr(d1,choice)) #获取内存地址,加括号直接调用
getattr(d1,choice)()

一般这么用:

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))

d1=Dog(hashiqi)
choice =input(input>>).strip()  #输入一个方法,如果方法在类中存在,则未true
if hasattr(d1,choice):
    func=getattr(d1,choice)  #增加一个变量,有助于传入参数
    func(baozi)  #将参数传给判断成功的方法

output:
input>>eat
hashiqi is eating baozi

动态装进取一个新方法:

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #输入一个方法,如果方法在类中存在,则未true
if hasattr(d1,choice):
    func=getattr(d1,choice)  #增加一个变量,有助于传入参数
    func(baozi)  #将参数传给判断成功的方法
else:
    setattr(d1,choice,bulk)
    d1.talk(d1)  #相当于调用类里面的talk方法,talk实际上就是类外面的bulk函数

output:
input>>talk
hashiqi is yelling

动态装进去一个属性

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #输入一个方法,如果方法在类中存在,则未true
if hasattr(d1,choice):
    func=getattr(d1,choice)  #增加一个变量,有助于传入参数
    func(baozi)  #将参数传给判断成功的方法,如果输入一个已经存在的属性,则不能加括号调用
else:
    # setattr(d1,choice,bulk)
    # d1.talk(d1)  #相当于调用类里面的talk方法,talk实际上就是类外面的bulk函数
    setattr(d1,choice,2)
    print(getattr(d1,choice))

output:
input>>asdf
2

删除一个属性

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #输入一个方法,如果方法在类中存在,则未true
if hasattr(d1,choice):
    delattr(d1,choice)
else:
    # setattr(d1,choice,bulk)
    # d1.talk(d1)  #相当于调用类里面的talk方法,talk实际上就是类外面的bulk函数
    setattr(d1,choice,2)
    print(getattr(d1,choice))

print(d1.name)

output:
    print(d1.name)
AttributeError: ‘Dog‘ object has no attribute ‘name‘

再变化

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #输入一个方法,如果方法在类中存在,则未true
if hasattr(d1,choice):
    getattr(d1,choice)
else:
    setattr(d1,choice,bulk)
    func = getattr(d1,choice) #  这里不管choice输入任何东西,都只调用bulk 就是把字符串choice反射成内存中bulk的地址
    func(d1)

 

异常处理

try:
    可能出错的语句
except 错误关键字1 as 别名:  别名捕获了错误的详细信息
    处理语句
except 错误关键子2 as 别名:
    处理语句
或者
except (错误关键字1,错误关键字2,。。。) as 别名:
    多个错误无法定位
except Exception:
    不管什么错误都放到这里,不建议一开始用
else:
    如果except都没有捕捉到异常
    就在这里处理
finally:
    不管有没有出现错误,都会执行

 自定义异常

class CustomException(Exception):
    def __init__(self,msg):
        self.msg=msg

try:
    raise CustomException(error) #这里实例化一个类了
except CustomException as e:  # e保存的就是msg的值
    print(e)

output:
error

 





以上是关于python3.x 基础七:面向对象进阶的主要内容,如果未能解决你的问题,请参考以下文章

Python基础-week06 面向对象编程进阶

进阶学Python:Python面向对象基础!

python面向对象进阶

Python基础-第七天-面向对象编程进阶和Socket编程简介

面向对象进阶

面向对象进阶——内置方法