python 吐血总结 【面向对象小结】

面向对象

面向对象和面向过程区别

面向过程编程:

类似于工厂的流水线

优势:逻辑清晰

缺点:扩展性差

面向对象编程:

核心是对象儿子,对象属性和方法的集合体,面向对象编程就是一堆对象交互

优点:扩展性好

缺点:逻辑乱,难理解

类与对象

对象:属性和方法的集合体

类:一系列相同属性和方法的集合体

现实世界先有对象后有类

python里面中先有类,再实例化出对象。  (可以说是工厂)

对象的属性的查找顺序

对象本身的属性——类——父类——父类的父类——object——自定义元类——type

给对象定制独有属性

class People:
    pass

p1 = Peolple()
p1.name = 'randy'

p2 = People()
p2.name = 'laowang'

对象的绑定方法

class People:
    def eat(self):
        print(self, 'eat....')

p1 = Peolple()
p1.eat() 
p1.name = 'jackson'

p2 = People()
p2.eat()
p2.name = 'alin'

反射

什么是反射?

通过字符串映射object对象的方法或者属性

反射是一个很重要的概念,它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。

它有四个重要的方法:

hasattr(obj,name_str): 判断objec是否有name_str这个方法或者属性
getattr(obj,name_str): 获取object对象中与name_str同名的方法或者函数
setattr(obj,name_str,value): 为object对象设置一个以name_str为名的value方法或者属性
delattr(obj,name_str): 删除object对象中的name_str方法或者属性

 

 

 

可能有些人还没明白反射,反射就是把字符串反射成内存对象,看下面的例子

getattr

class User:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print('%s 正在吃夜宵 ...' % self.name)

    def run(self):
        print('%s 正在跑步中 ...' % self.name)


#  场景: 当用户在操作时,面对用户不同的操作就需要调用不同的函数
#  如果用if,elif语句的话,会存在一个问题,当用户有500个不同的操作,
#  就需要写500次if,elif。这样就会出现代码重复率高,而且还不易维护
#  这时候反射就出现了,通过字符串映射对象或方法

# 实例化一个对象: Jackson
c = User('Jackson')

# 用户输入指令
choose = input('>>>:')

# 通过hasattr判断属性/方法是否存在
if hasattr(c, choose):
    # 存在,用一个func接收
    func = getattr(c, choose)
    # 通过类型判断是属性还是方法
    if type(func) == str:
        print(func)
    else:
        func()
else:
    print('操作有误,请重新输入')

setattr

class User:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print('%s 正在吃夜宵 ...' % self.name)

    def run(self):
        print('%s 正在跑步中 ...' % self.name)

def sing(self):
    print("%s 正在唱歌中..." % self.name)


choice = input('>>>:')
c = User('Jackson')

if hasattr(c, choice):
    func = getattr(c, choice)
    print(func)
else:
    # 装饰一个方法或者属性,这里装饰的是一个sing方法
    setattr(c, choice, sing)
    func = getattr(c, choice)
    func(c)

delattr就不多说了都差不多

反射的实际应用场景

在我们做接口自动化的时候,需要通过不同的请求方式,调用不同的函数

 

原始方法的代码

import requests
 
class Http(object):
 
 
    def get(self,url):
        res = requests.get(url)
        response = res.text
        return response
 
    def post(self,url):
        res = requests.post(url)
        response = res.text
        return response
 
# 使用反射前
url = "https://www.jianshu.com/u/14140bf8f6c7"
method = input("请求方法>>>:")
 
h = Http()
if method.upper() == 'GET':
    result = h.get(url)
elif method.upper() == 'POST':
    result = h.post(url)
else:
    print('请求方式有误....')
print(result)

反射之后的代码

import requests
 
class Http(object):
 
 
    def get(self,url):
        res = requests.get(url)
        response = res.text
        return response
 
    def post(self,url):
        res = requests.post(url)
        response = res.text
        return response
 
# 使用反射后
url = "https://www.jianshu.com/u/14140bf8f6c7"
method = input("请求方法>>>:")
h = Http()
 
if hasattr(h,method):
    func = getattr(h,method)
    res = func(url)
    print(res)
else:
    print("你的请求方式有误...")
 
这样就不用疯狂if elif elif 了,也可以说是Django里面的类视图。

 

列举面向对象带双下划线得魔术方法

property

classmethod

staticmethod

https://www.cnblogs.com/jackson669/p/12861886.html

 

(今晚补充内容)

__setitem__

__getitem__

__delitem__

class Foo:
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        print('[]获取值的时候触发')
        print('getitem执行', self.__dict__[item])

    def __setitem__(self, key, value):
        print('obj[key]=randy赋值时,执行我')
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('del obj[key]时,delitem执行')
        self.__dict__.pop(key)

    def __delattr__(self, item):
        print('del obj[key]时,执行我')
        self.__dict__.pop(item)


f1 = Foo('sb')
总结:
__setitem__  正括号赋值时触发
__getitem__ 正括号取值时候触发
__delitem__ 删除时候触发

 

 

 

posted @ 2020-05-31 21:31  我和姚明一样高  阅读(211)  评论(0编辑  收藏  举报