8.面向对象

一、类的属性问题

添加对象属性

可以在类中,在__init__方法中使用self.属性名 = 值,在内外使用对象名.属性名 = 值

添加类的静态属性

类中但是不再__init__方法中,属性名=值,在类外,类名.属性名 = 值。

对象找类属性的顺序

先在本类中找,找不到再去父类中找

类的私有属性

__private_attrs:两个双下划线开头,表明为私有属性,不能在类外被使用或直接访问

在python中私有属性的实现是通过改名实现的,python内部会将私有属性__name改成_A__name,这是可操作__name属性的,这中叫语言特性的名称改写。

类的保护属性

_x 单下划线的保护属性

python程序员约定不在类的外部使用该属性,实际上通过对象.保护属性名是可以访问的。

二、类与类之间的关系

2.1 依赖关系

一个类的对象可以作为另一个类中方法的参数,在该方法中可以调用该对象拥有的方法。

class A:
    def __init__(self):
        pass
    def funca(self):
        print('你好')
class B:
    def __init__(self):
        pass
    def funcb(self, obj):
        obj.funca()

a = A()
b = B()
b.funcb(a)		# 你好

2.2 关联,聚合,组合

组合:将一个类的对象封装到另一个类的对象的属性中,就叫组合。

另一个类的对象可以调用这个类对象的属性个方法。

三、继承与多态

继承的优点:

  • 增加了类的耦合性
  • 减少了重复代码
  • 使得代码更加规范化,合理化

3.1 继承的分类

单继承和多继承:

# 多继承
class A(object):
    def func(self):
        print("A")

class B(A):
    def func(self):
        super().func()
        print('B')
    
class C(A):
    def func(self):
        super().func()
        print('C')

class D(B,C):
    def func(self):
        super().func()
        print('D')

D().func()
# 找的顺序是DCBA,执行顺序为ABCD

3.2 多态

父类对于子类的约束,只要有这种类,子类必须实现和父类中同名的方法

实现多态的方法,抽象类。子类继承一个抽象类并重写抽象类中的方法。

# 父类对于子类的约束,只要有这种类,子类必须实现和pay同名的方法
# class Payment():
#     def pay(self, money):   # money参数在子类中也是必须的
#         raise NotImplementedError('请在子类中重写pay方法')
# 实现抽象类的类一种方法,约束性强,但是依赖abc模块
from abc import ABCMeta, abstractclassmethod
class Payment(metaclass=ABCMeta):
    @abstractclassmethod
    def pay(self, money):   # money参数在子类中也是必须的
        raise NotImplementedError('请在子类中重写pay方法')

3.3 实例化

实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。

实例化所经历的步骤

  1. 类名() 之后的第一个事儿 :开辟一块儿内存空间
  2. 调用 __init__ 把空间的内存地址作为self参数传递到函数内部
  3. 所有的这一个对象需要使用的属性都需要和self关联起来
  4. 执行完init中的逻辑之后,self变量会自动的被返回到调用处(发生实例化的地方)

四、反射

反射可以把字符串映射到实例的变量或者实列的方法然后去执行或者调用、修改等。四个重要的方法:

  • getattr 获取指定字符串名称的对象属性
  • hasattr 判断对象是否有对应的对象(字符串)
  • setattr 为对象设置一个对象
  • delattr 删除指定对象

属性指的是类中类变量、实例变量和方法。

什么对象可以使用反射?

实例化对象、类、其他模块、本模块

class A:
    name = 'an'
    def func(self):
        pritn('333')
content = input('请输入:').strip()
ret = getattr(A, content)
print(ret)
# 结果一
请输入:name
an
# 结果二
请输入:func
<function A.func as 0x2a5d11111>

只能反射类中有的属性或方法,不然会报错。

1、实例化对象的反射操作

class A:
    country = "中国"
    area = "上海"
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def func(self):
        print("123")
a = A("an", 18)     

# 变量名是以字符串形式使用的
print(hasattr(a, "name"))
# 一般hasattr和getattr结合使用
if	hasattr(a, "name"):
    print(getattr(a, "name"))	# an

# 可以设置默认值,没有该属性时返回默认值
print(getattr(a, "sex", None))

# 反射属性
print(getattr(a, "country"))	# 中国

# 反射方法
ret = getattr(a, "func")
print(ret())

# 给对象添加属性
setattr(a, "sex", "男)
        
# 删除对象属性
delattr(a, "sex")

2、类名的反射操作

class A:
    country = "中国"
    area = "上海"
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def func(self):
        print("123")
        
# 获取类的静态属性
print(getattr(A, "country"))
print(getattr(A, "area"))
# 获取类的方法并执行
getattr(A, "func")()

3、其他py文件的反射操作

假设一个demo.py文件

flag = True
def func(n)
	return n

class A:
    name_list = ["an", "bn", "cn"]
    def __init__(self, name, sex):
        self.name = name
        self.sex = sex
    def func(self):
        print("123")

在本py文件中,不用反射的操作方法

import demo.py
print(demo.flag)	# True

ret = demo.func
print(ret(111))		# 111

4、在本py文件的反射操作:反射的主体是本文件

五、内置的魔术方法

_new_

_call_ 对象调用这个类中的__call__方法

_len_ len(对象)需要实现类中的__len__方法

_eq_

_str_ 返回一个对象的描述信息,

class Cat:
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return self.name
tom = Cat('汤姆')
print(tom)

image-20201011111715973

_repr_ 返回对象的描述信息,与__str__方法不同的是此方法在控制台中直接打印或者使用print()方法打印的结果是相同的

image-20201011111520154

六、装饰器函数

@classmethod 传入cls表示当前类

class Goods:
    __discount = 0.8
    def __inti__(self):
        self.__price = 5
        self.price = self.__discount*self.__price
    # 把一个对象绑定的方法修改成类绑定的方法
    # 在方法中可以应用类中的静态变量,不用实例化对象
    @classmethod
    def change_discount(cls,new_discount):
        cls.__discount = new_discount

Goods.change_discount(0.6)
import time
class Date:
    def __init__(self,year, month, day):
        self.year = year
        self.month = month
        self.day = day
    @classmethod
    def today(cls):
        struct_t = time.localtime()
        date = cls(struct_t.tm_year, struct_t.tm_mon, struct_t.tm_mday)
        return date

date = Date.today()
print(date.year)
print(date.month)
print(date.day)

@staticmethod 静态方法

class User:
    # 类外函数放到类内,不用self参数,也不用实例化
    @staticmethod
    def login():
        pass

User.login()

七、可能用到的方法

isinstance(对象,类名) # 判断对象是否由该类实例化的

posted @ 2020-07-13 17:10  journeyerxxx  阅读(206)  评论(0编辑  收藏  举报
返回顶部