ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

面向对象3

2022-07-28 19:05:47  阅读:130  来源: 互联网

标签:name stu self 面向对象 print class def


一、派生方法实战演练(重要)

import datetime
import json

d = {
    't1': datetime.datetime.today(),
    't2': datetime.date.today()
}
res = json.dumps(d)
print(res)

image

上述代码报错,无法正常序列化,这是因为json序列化python数据类型是有限制的,不是所有类型都可以

即将被序列化的数据,内外都必须是一下类型才可以

python json
dict object
list,tuple arrary
str string
int,float number
bool True/False
None null

1.解决方式一:手动将不符合数据类型要求的数据转成符合要求的

import datetime
import json

d = {
    't1': str(datetime.datetime.today()),
    't2': str(datetime.date.today())
}
res = json.dumps(d)
print(res)  # {"t1": "2022-07-28 15:00:15.153789", "t2": "2022-07-28"}

2.解决方式二:派生方法

class JSONEncoder:
    pass
dumps(obj,cls=None):
    if cls == None:
        cls = JSONEncoder
    return cls(...)   # JSONEncoder()

查看JSONEncoder源码发现序列化报错是由default方法触发的

image

我们如果想要避免报错 那么肯定需要对default方法做修改(派生)

import datetime
import json

d = {
    't1': datetime.datetime.today(),
    't2': datetime.date.today()  # {"t1": "2022-07-28 15:10:25", "t2": "2022-07-28"}
}


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


res = json.dumps(d, cls=MyJsonEncode)
print(res)  # {"t1": "2022-07-28 15:10:25", "t2": "2022-07-28"}

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

1.简介

封装:将数据或者功能隐藏起来(包起来,装起来)

隐藏的目的:给这些隐藏的数据开设特定的接口,让用户使用接口才可以去使用,我们在接口中添加一些额外的操作

在类定义阶段使用双下划线开头的名字都是隐藏的属性,后续类和对象都无法直接获取

在python中不会真正的限制任何代码,隐藏的属性如果真的需要访问也可以,只不过需要做变形处理

2.代码示例

class Student(object):
    __school = '清华大学'
    def __init__(self, name, age):
        self.__name = name
        self.__age = age
    # 专门开设一个访问学生数据的通道(接口)
    def check_info(self):
        print("""
        学生姓名:%s
        学生年龄:%s
        """ % (self.__name, self.__age))
    # 专门开设一个修改学生数据的通道(接口)
    def set_info(self,name,age):
        if len(name) == 0:
            print('用户名不能为空')
            return
        if not isinstance(age,int):
            print('年龄必须是数字')
            return
        self.__name = name
        self.__age = age

stu1 = Student('jason', 18)
stu1.set_info('','我很大')

我编写python很多时候都是大家墨守成规的东西,不需要真正的限制

class A:
	_school = '清华大学'
	def _choice_course(self):
		pass

三、property伪装属性

1.简介

property伪装属性:将方法伪装成数据,伪装之后可以将func方法伪装成数据(obj.func)

obj.name   # 数据只需要点名字
obj.func()  # 方法还要加括号

2.代码示例

BMI指数是用来衡量一个人的体重与身高对健康影响的一个指标,计算公式为

体质指数(BMI)=体重(kg)÷身高^2(m)

身高或体重是不断变化的,因而每次想查看BMI值都需要通过计算才能得到,但很明显BMI听起来更像是一个特征而非功能,为此Python专门提供了一个装饰器property,可以将类中的函数“伪装成”对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果,例如

class Person:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    @property
    def BMI(self):
        return self.weight / (self.height ** 2)


p = Person('jason', 78, 1.83)
res = p.BMI()
print(res)

使用property有效地保证了属性访问的一致性。另外property还提供设置和删除属性的功能,如下

class Foo:
    def __init__(self, val):
        self.__NAME = val  # 将属性隐藏起来

    @property
    def name(self):
        return self.__NAME

    @name.setter
    def name(self, value):
        if not isinstance(value, str):  # 在设定值之前进行类型检查
            raise TypeError('%s must be str' % value)
        self.__NAME = value  # 通过类型检查后,将值value存放到真实的位置self.__NAME

    @name.deleter
    def name(self):
        raise PermissionError('Can not delete')


obj = Foo('jason')
# print(obj.name)
# obj.name = 666
# print(obj.name)
del obj.name

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

1.简介

多态:一种事物的多种形态

  • 水:液态、气态、固态
  • 动物:猫、狗、猪

2.代码示例

一种事物有多种形态,但是相同的功能应该有相同的名字,以后我无论拿到哪个具体的动物,都不需要管到底是谁,直接调用相同的功能即可

class Animal: # 同一类事物: 动物
    def talk(self):
        pass


class Cat(Animal): # 动物的形态之一: 猫
    def talk(self):
        print('喵喵喵')


class Dog(Animal): # 动物的形态之二: 狗
    def talk(self):
        print('汪汪汪')


class Pig(Animal): # 动物的形态之三: 猪
    def talk(self):
        print('哼哼哼')


# 实例化得到三个对象
cat = Cat()
dog = Dog()
pig = Pig()

cat.talk()  # 喵喵喵
dog.talk()  # 汪汪汪
pig.talk()  # 哼哼哼


def Talk(animal):
    animal.talk()


Talk(cat)  # 喵喵喵
Talk(dog)  # 汪汪汪
Talk(pig)  # 哼哼哼

python也提供了一种强制性的操作(了解即可),应该是自觉遵守

import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
    def talk(self): # 抽象方法中无需实现具体的功能
        pass
class Person(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
    def talk(self):
        pass
    def run(self):
        pass
obj = Person()

五、面向对象之反射(重要)

1.简介

反射:通过字符串来操作对象的数据方法

2.反射的四个主要方法

方法 描述
hasattr() 判断对象是否含有某个字符串对应的属性
getattr() 获取对象字符串对应的属性
setattr() 根据字符串给对象设置属性
delattr() 根据字符串给对象删除属性
class Teacher:
    def __init__(self,full_name):
        self.full_name =full_name

t=Teacher('jason Lin')

# hasattr(object,'name')
hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name

# getattr(object, 'name', default=None)
getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None

# setattr(x, 'y', v)
setattr(t,'age',18) # 等同于t.age=18

# delattr(x, 'y')
delattr(t,'age') # 等同于del t.age

3.代码示例

需求:判断用户提供的名字在不在对象可以使用的范围内

class Student:
    school = '清华大学'

    def choice_course(self):
        print('选课')
stu = Student()

3.1.方式1:异常处理(过于繁琐)

try:
    if stu.school:
        print(f"True{stu.school}")
except Exception:
    print("没有属性")

变量名school(stu.school)与字符串school(stu.‘school’)区别:两者虽然只差了引号,但是本质是完全是不一样的

3.2.方式2:获取用户输入的名字,判断改名字有没有对象

异常处理不好实现,我们需要使用反射

while True:
    target_name = input('请输入您想要核查的名字>>>:').strip()
    '''上面的异常更加不好实现 需要用反射'''
    # print(hasattr(stu, target_name))
    # print(getattr(stu, target_name))
    if hasattr(stu, target_name):
        # print(getattr(stu, target_name))
        res = getattr(stu, target_name)
        if callable(res):
            print('拿到的名字是一个函数', res())
        else:
            print('拿到的名字是一个数据', res)
    else:
        print('不好意思 您想要查找的名字 对象没有')
print(stu.__dict__)
stu.name = 'jason'
stu.age = 18
print(stu.__dict__)
setattr(stu, 'gender', 'male')
setattr(stu, 'hobby', 'read')
print(stu.__dict__)
del stu.name
print(stu.__dict__)
delattr(stu, 'age')
print(stu.__dict__)

3.3.总结

以后只要在需求中看到了关键字....对象....字符串,那么肯定需要使用反射

4.反射实战演练

class FtpServer:
    def serve_forever(self):
        while True:
            inp = input('input your cmd>>: ').strip()
            cmd, file = inp.split()
            if hasattr(self, cmd):  # 根据用户输入的cmd,判断对象self有无对应的方法属性
                func = getattr(self, cmd)  # 根据字符串cmd,获取对象self对应的方法属性
                func(file)

    def get(self, file):
        print('Downloading %s...' % file)

    def put(self, file):
        print('Uploading %s...' % file)

操作系统

Linux系统

linux系统:一切皆文件(只要能读数据,能写数据,那么就是文件)

class Txt:  # Txt类有两个与文件类型同名的方法,即read和write
    def read(self):
        pass

    def write(self):
        pass


class Disk:  # Disk类也有两个与文件类型同名的方法:read和write
    def read(self):
        pass

    def write(self):
        pass


class Memory:  # Memory类也有两个与文件类型同名的方法:read和write
    def read(self):
        pass

    def write(self):
        pass

Python

python:一切皆对象(只要有数据,有功能,那么就是对象)

  • 文件名→文件对象
  • 模块名→模块对象

标签:name,stu,self,面向对象,print,class,def
来源: https://www.cnblogs.com/NianBai/p/16529295.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有