面向对象编程(三)

面向对象编程(三)

一、上节内容回顾

1、动静态方法

类体代码中编写函数的三种类型
1.绑定给对象的方法:
  类中直接定义函数,默认绑定给函数,对象调用自动当做第一个参数传入
  eg:
    class Student:
        def func1(self):    
            print('nnnn')
    obj = Student()
    onj.func1()
    Student.func1()     # nnnn
2.绑定给类的方法:
  类、对象自动将产生该对象的类当做第一个参数传入
  eg:
    class Student:
        @classmethod    # 绑定类的方法
        def index(cls):
            print('nnnn',cls)
    obj = Student()
    Student.index()
    obj.index()               # nnnn <class '__main__.Student'>
 3.普普通通的函数
   静态方法:
   eg:
    class Student:
    @staticmethod  # 静态方法
    def index(a):
        print('nnnn',a)
obj = Student()
Student.index(123)
obj.index(123)            # nnnn 123

2.面向对象三大特性之继承

继承:让类继承了另一个类,转为父子关系
继承主要的目的:可以减少代码编写
继承的类:子类、派生类
被继承的类:父类、超类、基类

3.对象查找属性的顺序

1.不继承
  对象自身--->> 产生对象的类
2.单继承
  对象自身--->> 产生对象的类---->>类的父类
3.多继承
  对象自身--->> 产生对象的类---->>类的父类(从左往右)

二、派生方法的实战

1.派生方法

super():子类调用父类的方法
派生方法通俗讲就是当运行模块函数时可以在途中进行拦截然后添加自己需要添加的操作然后再返回继续执行原本的模块函数。

2.能够支持json序列化的数据类型

    +-------------------+---------------+
    | Python            | JSON          |
    +===================+===============+
    | dict              | object        |
    +-------------------+---------------+
    | list, tuple       | array         |
    +-------------------+---------------+
    | str               | string        |
    +-------------------+---------------+
    | int, float        | number        |
    +-------------------+---------------+
    | True              | true          |
    +-------------------+---------------+
    | False             | false         |
    +-------------------+---------------+
    | None              | null          |
    +-------------------+---------------+
 
'''ps:要进行序列化的数据必须全部都是上述类型才可以'''
import json
import datetime

d = {
    't1': datetime.datetime.today(),
    't2': datetime.date.today(),
}
res = json.dumps(d)
print(res)
# 会报错,因为字典值是日期型,不能被序列化
解决:通过派生方法拦截dumps内置函数吧数据进行转换再序列化
import json
import datetime

d = {
    't1': datetime.datetime.today(),
    't2': datetime.date.today(),
}
class MyJsonEncoder(json.JSONEncoder):
    def default(self, data):
        # data就是json即将要序列化的数据
        if isinstance(data,datetime.datetime):
            return data.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(data, datetime.date):
            return data.strftime('%Y-%m-%d')
        # 如果是可以序列化的类型 那么不做任何处理 直接让它序列化即可
        return super().default(data)


res = json.dumps(d,cls=MyJsonEncoder)
print(res)
json.dumps(d,cls=MyJsonEncoder)
# {"t1": "2022-11-07 16:36:19", "t2": "2022-11-07"}

三、面向对象三大特性之封装

1.封装的简介

封装确实就是把数据和功能‘封装’起来,隐藏对象的数据和功能,隐藏的数据开设特定的接口用户需要使用接口才能使用,能够提高程序的安全性
隐藏:将数据和功能隐藏起来,开发一些接口,从而可以在接口内添加额外的操作
伪装:将类里的方法伪装类里面的数据

2.隐藏属性

在类定义阶段使用双下划线开头的名字都是隐藏属性
隐藏的数据不是让用户无法使用 只不过需要做变形的处理
    (用改变后的名字去访问隐藏数据就失去了隐藏的意义)
      __变量名              __类名__变量名
class Person:
    def __init__(self,name,age):
        self.__name = name   # 对象也有隐藏属性
        self.__age = age

    def get_info(self):   # 实体代码中科院直接使用隐藏的名字
        print(f"""
            姓名:{self.__name}   
            年龄:{self.__age}
        """)

obj = Person('jj',18)
obj.get_info()

#  姓名:jj    年龄:18

3.property伪装属性

property可以简单的理解为吧方法伪装成数据
eg:
    将方法obj.func()伪装成数据obj.func
class Person:
    def __init__(self,chinese,math,English):
        self.chinese = chinese
        self.math = math
        self.English = English
    @property
    def avage(self):
        return (self.English+self.chinese+self.math) / 3

obj = Person(80,90,89)     # 不需要写括号
print(obj.avage)    # 86.33333333333333

四、面向对象三大特性之多态

1.动态的作用

    一种事物的多种不同形态,比如衣服它可以是长袖、短袖、衬衫、卫衣等等不同的形态但都有衣服的固定功能。
    一种事物可以有多种形态但是针对相同的功能应该定义相同的方法,这样无论我们拿到的是哪个具体的事物 都可以通过相同的方法调用功能

2.代码实现

class Clothes(object):
    def ornament(self):
        pass
class Sleeves(Clothes):
    def ornament(self):
        print('穿的短袖')
class Sweat(Clothes):
    def ornament(self):
        print('穿的卫衣')
class Dress(Clothes):
    def ornament(self):
        print('穿的裙子')
s1 = Sleeves()
s2 = Sweat()
s3 = Dress()

s1.ornament()   '''穿的短袖'''
s2.ornament()   '''穿的卫衣'''
s3.ornament()   '''穿的裙子'''
Python也提供了一种强制性的操作,指定metaclass属性类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
import abc

class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def talk(self):
        pass
class Person(Animal):
    def talk(self):
        pass
    def run(self):
        pass

obj = Person()

五、面向对象之反射

1.反射的作用

  可以用字符串的方式操作对象的数据或者方法,当看到需求中有字符串和对象时可以肯定需要反射来做。

2.反射的四个主要的方法

hasattr():判断一个对象中是否有某个字符串对应的属性
getattr():获取对象字符串对应的属性  一般hasattr和getattr结合使用
setattr():根据字符串给对象设置属性
delattr():根据字符串给对象删除属性
class Person:
    type = '一个人'
    def profile(self):
        print('小美女子')
obj = Person()
while True:
    target_name = input('请输入你要查找的名字>>>:').strip()
    if hasattr(obj, target_name):
        print(getattr(obj, target_name))
    else:
        print('对不起,没找到你要的对象')
 
'''打印结果
请输入你要查找的名字>>>:type
是个人
请输入你要查找的名字>>>:profile
<bound method Person.profile of <__main__.Person object at 0x7fba284c6fd0>>
'''
class Person:
    type = '一个人'
    def profile(self):
        print('小美女子')
obj = Person()
 
setattr(obj,'name','aa') # 对象没有这个属性则添加属性
setattr(obj,'age',18) # 对象没有这个属性则添加属性
print(obj.age)
 
delattr(obj,'name') # 删除对象内的属性
print(obj.__dict__)
 
'''打印结果
18
{'age': 18}
'''
posted @ 2022-11-07 19:10  小王应该在学习!  阅读(19)  评论(0编辑  收藏  举报