首页 > 其他分享 >周总结7

周总结7

时间:2022-11-14 19:22:47浏览次数:45  
标签:总结 __ obj name self class def

面向对象之封装,多态,反射

派生实际应用

  import datetime
  import json
import datetime
  import json

  class MyJsonEncoder(json.JSONEncoder):
      def default(self, o):
          # 形参o就是即将要被序列化的数据对象
          # print('重写了', o)
          '''将o处理成json能够序列化的类型即可'''
          if isinstance(o,datetime.datetime):
              return o.strftime('%Y-%m-%d %X')
          elif isinstance(o, datetime.date):
              return o.strftime('%Y-%m-%d')
          return super().default(o)  # 调用父类的default(让父类的default方法继续执行 防止有其他额外操作)

  d1 = {'t1': datetime.datetime.today(), 't2': datetime.date.today()}
  res = json.dumps(d1, cls=MyJsonEncoder)
  print(res)
  """
  TypeError: Object of type 'datetime' is not JSON serializable
  json不能序列化python所有的数据类型 只能是一些基本数据类型
      json.JSONEncoder

  1.手动将不能序列化的类型先转字符串
      {'t1': str(datetime.datetime.today()), 't2': str(datetime.date.today())}
  2.研究json源码并重写序列化方法
      研究源码发现报错的方法叫default
          raise TypeError("Object of type '%s' is not JSON serializable" % o.__class__.__name__)
      我们可以写一个类继承JSONEncoder然后重写default方法
"""
能够被序列化的数据是有限的>>>:必须是下列左边的类型
+-------------------+---------------+
| Python            | JSON          |
+===================+===============+
| dict              | object        |
+-------------------+---------------+
| list, tuple       | array         |
+-------------------+---------------+
| str               | string        |
+-------------------+---------------+
| int, float        | number        |
+-------------------+---------------+
| True              | true          |
+-------------------+---------------+
| False             | false         |
+-------------------+---------------+
| None              | null          |
+-------------------+---------------+

面向对象三大特性之封装

封装的含义:
就是将数据与功能隐藏起来,不能直接调用,必须使用单独开发的接口来调用这些隐藏起来的数据并利用该接口添加额外的操作。分为 封装与隐藏

1.封装: 就是将数据和功能封装起来。

2.隐藏: 将数据与功能隐藏起来,只能通过接口调用并增加额外的操作

​ 类在定义阶段变量名前有两个下划线,就是隐藏该名字,功能也可以使用两个下划线来隐藏

我们可以直接通过'_Student__school' 与 '_Student__choice_course'这两个名字来访问,但是这样是不可取的,隐藏就是为了让你不要直接去访问他,你这样还有啥意思。自觉遵守。

"""要注意的是类只有在定义阶段才可以隐藏,如果你在下面使用 类名.隐藏名 修改数据 那么隐藏就无效了"""

对象也可以拥有隐藏属性

class Student(object):
    school_name = '考上大学啦'
    __school = '家里蹲大学'

    def __init__(self, name, age):
        self.__name = name
        self.__age = age
    # 开放修改接口,并增加一些特殊功能,
    '如果年龄也需要修改,只需在形参里加上年龄'
    def set_name(self,new_name):
        if len(new_name)== 0:  # 判断用户输入的名字是否为空
            raise ValueError('你啥都不输什么意思')
        if new_name.isdigit():  # 判断用户输的名字是否是数字
            raise ValueError('让你输个名字你输数字搞毛啊')
        self.__name = new_name

obj = Student('tank',18)
print(obj.__dict__)  # {'_Student__name': 'tank', '_Student__age': 18}
obj.set_name('jason')  # 利用接口修改隐藏名字的数据
print(obj.__dict__)  # {'_Student__name': 'jason', '_Student__age': 18}

"我们在隐藏一些名字的同时,应该开放一个修改这些 名字的数据值 的接口,同时还能加上一些判断或别的"

伪装

 @property  可以将方法伪装成数据
class Person(object):
    def __init__(self, name, height, weight):
        self.name = name
        self.height = height
        self.weight = weight

    @property
    def BMI(self):
        return '%s您的BMI指数是%s' % (self.name, self.weight / (self.height ** 2))

obj = Person('lxj',1.78,75)
obj.BMI()  # 报错 此时方法已经被转成基本数据
print(obj.BMI) # lxj您的BMI指数是23.671253629592222

三大特性之多态

多态:一种事物的多种形态
eg:
    动物:猪狗牛羊猫

    
class Animal(object):
    def speak(self):
        pass

class Chicken(Animal):
    def speak(self):
        print('咯咯咯')

class Duck(Animal):
    def speak(self):
        print('嘎嘎嘎')

class Sheep(Animal):
    def speak(self):
        print('咩咩咩')

"动物,我们只要提起动物那么第一时间就想起了动物们都会叫,那么他们就应该有一个共同的方法 叫"
C1 = Chicken() # 模拟鸡
D1 = Duck()  # 模拟鸭
S1 = Sheep()  # 模拟羊
C1.speak()  # 咯咯咯
D1.speak()  # 嘎嘎嘎
S1.speak()  # 咩咩咩
"""面向对象中多态意思是 一种事物可以有多种形态但是针对相同的功能应该定义相同的方法
这样无论我们拿到的是哪个具体的动物 都可以通过相同的方法调用功能。

我们如何来寻找共同的特征的方法:
在python中称为:鸭子类型:只要你看上去像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子
"""

多态提供了强制约束子类的方法: 不推荐使用
import abc
# 指定metaclss 属性将设置为抽象类,抽象类本身只能用于约束子类
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod  # 使用 该装饰器 现在子类必须要有 speak方法
    def speak(self):
        pass

class Chicken(Animal):  # 只要继承Animal 必须要有 speak方法
    def speak(self):
        print('咯咯咯')

class Duck(Animal):
    def jiao(self):   # 没有speak方法
        print('嘎嘎嘎')

D1 = Duck()  # 直接报错  TypeError: Can't instantiate abstract class Duck with abstract methods speak

"""
在linux系统中有一句话>>>:一切皆文件!!!
    内存可以存取数据
    硬盘可以存取数据
    那么多有人都是文件
"""
class Memory(object):  # 内存
    def read(self):
        pass
    def write(self):
        pass
class Disk(object):  # 磁盘
    def read(self):
        pass
    def write(self):
        pass
# 得到内存或者硬盘对象之后 只要想读取数据就调用read 想写入数据就调用write 不需要考虑具体的对象是谁

三大特性之反射

利用字符串操作对象的数据和方法
1.hasattr() 
	'判断对象是否含有某个字符串对应的属性名或方法名'
2.getattr() 
	'根据字符串获取对象对应的属性名(属性的值)或方法名(函数名及代码)'
3.setattr()
	根据字符串给对象设置或修改数据
4.delattr()
	根据字符串删除对象里面的名字

在于用户交互的情况下,我们得到用户输入的值都是字符串,无法通过字符串来直接找到该名字。此时就有了反射
class A:
    name = 'tank'

    def get(self):
        pass


obj = A()
target_name = input('请输入你想要对象使用的名字').strip()
hasattr() 
print(hasattr(obj,target_name))  # 用户输入name   得到True  
print(hasattr(obj,target_name))  # 用户输入get     True
print(hasattr(obj,target_name))  # 用户输入age   此时类的名称空间内并没有这个名字False


getattr()
print(getattr(obj,target_name))   # 用户输入name  得到  值 tank
 

面向对象的魔法方法

类中定义的双下方法都称为魔法方法.
在特定的条件下自动触发运行,不需要人去调用

__init__方法

'对象添加独有数据时'自动触发
class A:
    def __init__(self,name):
        self.name = name

obj = A('tank')  #  等同于  obj.name = tank
"在我们生成对象时,传值的时候就等于self.name = 传的值  此时就会自动触发"

__str__方法

'对象被执行打印操作时'自动触发
class A:
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return '今天是个好日子'
obj = A('tank')
print(obj)  # 今天是个好日子
"返回的是字符串。如果返回字符串以外的数据类型则直接报错"

__call__方法

'对象加括号调用'就会自动触发
class A:
    def __init__(self,name):
        self.name = name

    def __call__(self, *args, **kwargs):
        print('我触发了哦',args,kwargs)
        return '起飞'

obj = A('tank')
print(obj(111))
'''我触发了哦 (111,) {}
  起飞
'''
args 是个空元组用来接收参数
kwargs 是个空列表 用来接收关键字传参

__getattr__方法

对象 '点'不存在的'名字'的时候自动触发
class A:
    def __init__(self,name):
        self.name = name

    def __getattr__(self, item):
        print('item是不存在的名字:',item)

obj = A('tank')
print(obj.age)  # item是不存在的名字: age
'在正常情况下点一个不存在的名字会报错'

__getattribute__方法

对象点名字就会自动触发,有它在就不会触发
class A:
    def __init__(self,name):
        self.name = name
    def __getattr__(self, item):
        print('我是你大哥')
    def __getattribute__(self, item):
        print('有我在就不会执行双下__getattr__')

obj = A('tank')
print(obj.age) # 有我在就不会执行双下__getattr__

__setattr__方法

给对象添加或者修改数据的时候自动触发  对象.名字 = 值
class A:
    def __init__(self, name):
        self.name = name

    def __setattr__(self, key, value):
        print('执行setattr:', key, value)


obj = A('tank')  # 执行setattr: name tank
obj.age = 18  #  执行setattr: age 18

enter 方法

__exit__方法

__enter__当对象被当做with上下文管理操作的开始自动结束。并且返回什么 as后面的变量名就会接收到什么
__exit__ with上下文管理语法运行完毕之后自动触发(子代码结束)
class A:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print('开始时执行我并接收我的返回值')
        return '哈哈哈'
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('子代码结束时执行')


obj = A('tank')
with obj as f:
    print(f)
============================
开始时执行我并接收我的返回值
哈哈哈
子代码结束时执行
============================

魔法方法之_new_

"""
双下new 用来产生空对象
双下init 用来实例化对象
"""

class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        obj = self.__new__(self)   # 产生一个空对象(骨架) 这里的括号内(self)其实是类
        self.__init__(obj,*args, **kwargs)  # 调用__init__给对象添加独有数据(血肉)   
        # 返回创建好的对象
        return obj

class Student(metaclass=MyMetaClass):
    def __init__(self,name):
        self.name = name

obj = Student('tank')
print(obj.__dict__)

元类简介

元类——产生类的类

我们之前查看数据类型都是用 type 方法查看,我们再看结果的时候看到前面的class不知道是什么 ,学过面向对象 后 class 这不就是类吗

使用type方法查看到 对象属于产生该对象的类

"""所以我们得到结论 type 就是所有类的元类 """

创建类的两种方式

第一种 使用 关键字 class
class B(object):
    pass
print(B)
# <class '__main__.B'>

第二种 type元类
我们通过查看type的源码查看到方法
'type(name, bases, dict) -> a new type'

type(类名,父类,名称空间)

元类定制类的产生行为

"""元类 能够控制类的创建,那么我们就可以在创建过程中添加各种额外操作"""
使用元类控制 产生所有的 类的时候 类名首字母必须是大写
我们在生产类的时候会自动触发元类的__init__方法来创建类,那么我们可以自定义一个元类,重写init方法。

1.元类定制类的产生行为:
class MyMetaClass(type):  # what 是类名, bases父类, dict 名称空间
    def __init__(cls, what, bases=None, dict=None):  # 重写init方法,会飘黄,因为正在修改元类的方法
        if not what.istitle():  # 添加判断
            raise Exception('类名首字母大写哦')  # 
        super().__init__(what,bases,dict)

# 指定类的元类 必须使用关键字 metaclass
class myclass(metaclass=MyMetaClass):
    pass  # Exception: 类名首字母大写哦

标签:总结,__,obj,name,self,class,def
From: https://www.cnblogs.com/LiaJi/p/16890093.html

相关文章

  • 51st 2022/11/12 模拟赛总结36
    这次按自己的话来说,不能接受因为和估分差距有点大赛时很开心地以为能A两题,一题50然后爆成120原因:T1的100->20现发现T1是因为没有全取模,很失落其实是因为考试时的一......
  • C++初阶(命名空间+缺省参数+const总结+引用总结+内联函数+auto关键字)
    命名空间概述在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的......
  • Linux下FastDFS分布式存储-部署过程和总结
    部署之前先对比下FastDFS和HDFS:1.fastDFS和HDFS(Hadoop的分布式存储)不同,fastDFS的文件不是切片存储的,一个文件被存储在其中某一个group组的所有storage节点上,一个组中的每......
  • 常用STL总结(详细 全)
    /*目录vectorpairstringqueuepriority_queuestackdequeuesetmapmultiset,multimapunordered_______map,set,multimap,multiset//基于哈希表实现*/#include<vector>intma......
  • 00后程序员摸爬滚打近一年,为学弟学妹们总结出了以下 7 条人生建议(建议收藏)
    前言     大家好,我是梦想家 。     前段时间我在发布了一篇文章,在很短的时间内便冲上了热榜,连续3天都处在Top3的位置,算是小火了一下。为了能让公众号......
  • 使用Linux自启动文件rc.local遇到的问题总结
    rc.local的执行权限在/etc/rc.local文件中添加启动脚本,重启后没有执行。是因为/etc/rc.local是个链接文件,权限始终是777。在实际执行时看的是源文件的执行权限,需要添加......
  • uniapp开发微信小程序分享二维码的相关功能问题总结
    近期项目,需要在基于uniapp开发的微信小程序上,添加分享图片(二维码)的功能,有些注意点需总结:1.分享图片功能,使用的是wx.showShareImageMenu() 而不是uniapp的uni.share()......
  • 自动化层次总结
      一、接口自动化应用框架:python+request+pytest+allure   testcase目录:用例目录一个模块创建一个目录每个目录中一个py文件和若干yaml文件py文件中一般......
  • ASP.NET Core中选项的应用和总结
    在前面的文章中,我们介绍过将appsetting等配置文件映射到实体的的方式https://www.cnblogs.com/fei686868/p/16779249.html这里呢,我们介绍关于选项的另一种用法,就是通过IOp......
  • javascript 高级编程 之 Array 用法总结
    引用类型是一种数据结构,用于将数据和功能联系起来。创建对象的方式:1.new操作符vararray=newArray();2.字面量表示法创建vararray=[];Array检测数组:检测数组......