昨日回顾

  • 反射

    • 用"字符串"类型的属性名/方法名来找到
    • 属性的值或者方法的内存地址
  • 所有可以反射的内容实际上都是变量 有内存地址
  • 内存地址存的是"具体的值",直接能取到结果
  • 内存地址存的是"函数\方法\类",取到的是内存地址
  • 有哪些东西你一打印打印出的是地址
    • 函数
    • 类中的各种方法

如何反射类

class Foo:pass
import sys
clas = getattr(sys.modules[__name__],'Foo')
print(clas)   # == Foo
obj = clas()   # Foo() 相当于实例化一个Foo对象的过程

如何反射函数

def func():print('12345')
import sys
func_addr = getattr(sys.modules[__name__],'func')
func_addr() # func()

如何反射变量

全局变量
a = {2,2,3}
import sys
b = getattr(sys.modules[__name__],'a')
print(b)

如何反射类里的成员

  • 类中的成员 : 静态变量 静态方法 类方法 对象方法 property方法
  • 习惯使用类调用的有哪些 : 静态变量 静态方法 类方法
  • 对象中的成员 : 对象属性
  • 习惯使用对象调用的有哪些:对象属性 对象方法 property方法
  • 类和对象中成员的反射 都是遵循"调用习惯"的
class Foo:
    Country = 'China'

    @classmethod
    def showCountry(cls):
        print('in showCountry',cls.Country)

    @staticmethod
    def wahaha():
        print('wahaha')
#类中的静态属性
print(getattr(Foo,'Country'))

类中的类方法

print(getattr(Foo, 'showCountry'))   # Foo.showCountry
getattr(Foo, 'showCountry')()   # Foo.showCountry()

类中的静态方法

getattr(Foo, 'wahaha')()   # Foo.wahaha()

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

    def eat(self):
        print(self.name + ' is eating')

alex = Student('alex',84)
print(getattr(alex,'name'))   # alex.name
print(getattr(alex,'age'))   # alex.age
getattr(alex,'eat')()    # alex.eat()
import time
import re
import os
import sys
import random
import json
import pickle
import collections
import hashlib

lst = [1,2,3,4,5]
random.shuffle(lst)
print(lst)

getattr(random,'shuffle')(lst)
print(lst)

isinstance(对象,类) 判断对象是不是这个类或者这个类的子类的对象
issubclass(类1,类2) 判断类1是不是类2的子类

内置方法

  • 90%
  • 内置方法 双下方法 魔术方法
  • 都是python的对象内部自带的
  • 并且都不需要我们自己去调用它

str

repr

class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period
    def __str__(self):
        '''打印这个对象的时候 自动触发__str__'''
        '''使用%s进行字符串的拼接的时候 自动触发__str__'''
        return '%s,%s,%s'%(self.name,self.price,self.period)

python = Course('python',25000,'6 months')
print(python)
print('course %s'%python)
print(f'course {python}')
#如果 不实现str方法,那么对象打印出来只是一串地址
l = [1,2,3]
#l是对象,打印的时候直接显示的是元素
print(l)
class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period

    def __repr__(self):   # 备胎
        return '%s,%s,%s'%(self.name,self.price,self.period)

    def __str__(self):
        return self.name

python = Course('python',25000,'6 months')
print(python)
print('course %s'%python)
print(f'course {python}')
print(repr(python))
print('course %r'%python)

如果str存在,repr也存在

  • 那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
  • 而repr(obj)和%r格式化字符串,都会调用__repr__

如果str不存在,repr存在

  • 那么print(obj),字符串格式化format,%s,%r 和repr(obj)都调用__repr__

如果str存在,repr不存在

  • 那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
  • repr(obj)和%r格式化字符串 都会打印出内存地址
class Course(object):
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period

    def __repr__(self):   # 备胎
        return '%s,%s,%s'%(self.name,self.price,self.period)

    # def __str__(self):
    #     return self.name

class Python(Course):
    pass
    # def __repr__(self):   # 备胎
    #     return '%s--%s--%s'%(self.name,self.price,self.period)

    # def __str__(self):
    #     return '全栈开发 :'+self.name

py20 = Python('python',25000,'6 months')
print(py20)

打印对象 先走自己的str,如果没有,走父类的,如果除了object之外的所有父类都没有str再回来,找自己的repr,如果自己没有,再找父类的

repr是str的备胎和所有的字符串格式化以及直接打印这个对象相关

str(obj),repr(obj)

流畅的python - repr

print(str('123'))
print(repr('123'))
  • 有了repr或者str在打印对象的时候 就不会显示用户不关心的内存地址了
  • 增强了用户的体验 在程序开发的过程中
  • 如果我们需要频繁打印对象中的属性,需要从类的外部做复杂的拼接,实际上是一种麻烦
  • 如果这个拼接工作在类的内部已经完成了,打印对象的时候直接就能显示

__new__ 构造方法 生产对象的时候用的 - 单例模式

__del__ 析构方法 在删除一个对象之前用的 - 归还操作系统资源

class Foo:
    def __new__(cls, *args, **kwargs):
        print('in new')   # 先执行
        obj = object.__new__(cls)
        print(obj)
        return obj

    def __init__(self):
        print('init',self)    # 后执行

Foo()
  • 实例化一个Foo的对象

    • 先开辟一块儿空间,使用的是Foo这个类内部的__new__

      • 如果我们的Foo类中是没有__new__方法的
      • 调用object类的__new__方法了
class Foo(object):
    def __new__(cls, *args, **kwargs): # cls永远不能使self参数,因为self在之后才被创建
        obj = object.__new__(cls)   # self是在这里被创造出来的
        print('new : ',obj)
        return obj
    def __init__(self):
        print('init',self)

Foo()
  • 在使用self之前,都还有一个生产self的过程

    • 就是在内存中开辟一块属于这个对象的空间,并且在这个空间中存放一个类指针
    • 以上就是__new__做的所有事情

设计模式 - 单例模式

一个类 有且只能有一个实例

class A:pass
a1 = A()
a2 = A()
print(a1)
print(a2)

class A:
    __flag = None
    def __new__(cls, *args, **kwargs):
        if cls.__flag is None:
            cls.__flag = object.__new__(cls)
        return cls.__flag

    def __init__(self,name=None,age=None):
        self.name = name
        if age:
            self.age = age

a1 = A('alex',84)
print(a1)
a2 = A('alex',83)
print(a2)
a3 = A('alex')
print(a3)
print(a1.age)

保证一个类无论 被实例化多少次,只开辟一次空间,始终使用的是同一块内存地址

__del__方法-python解释器

import time
class A:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __del__(self):
        # 只和del obj语法有关系,在执行del obj之前会来执行一下__del__中的内容
        print('执行我啦')

a = A('alex',84)
print(a.name)
print(a.age)
# del a   # 这个变量已经没了
time.sleep(1)
在所有的代码都执行完毕之后,所有的值都会被python解释器回收

python解释器清理内存

  1. 我们主动删除 del obj
  2. python解释器周期性删除
  3. 在程序结束之前 所有的内容都需要清空
import time
class A:
    def __init__(self,path):
        self.f = open(path,'w')
    def __del__(self):
        '''归还一些操作系统的资源的时候使用'''
        '''包括文件\网络\数据库连接'''
        self.f.close()

a = A('userinfo')
time.sleep(1)

__call__

源码里用比较多 Flask web框架

对象()自动触发__call__中的内容

class A:
    def call(self):
        print('in call')
    def __call__(self, *args, **kwargs):
        print('in __call__')

A()()
obj = A()
obj()
obj.call()

with的上下文处理

class File:
    def __enter__(self):
        print('start')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit')

with File():
    print('wahaha')
class myopen:
    def __init__(self,path,mode='r'):
        self.path = path
        self.mode = mode

    def __enter__(self):
        print('start')
        self.f = open(self.path,mode=self.mode)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()
        print('exit')

with myopen('userinfo','a') as f:
    f.write('hello,world')

pickle

import pickle
class MypickleDump:
    def __init__(self,path,mode = 'ab'):
        self.path = path
        self.mode = mode

    def __enter__(self):
        self.f = open(self.path,self.mode)
        return self

    def dump(self,obj):
        pickle.dump(obj,self.f)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

with MypickleDump('pickle_file') as pickle_obj:
    pickle_obj.dump({1,2,3})
    pickle_obj.dump({1,2,3})
    pickle_obj.dump({1,2,3})
    pickle_obj.dump({1,2,3})
    pickle_obj.dump({1,2,3})
    pickle_obj.dump({1,2,3})
class MypickelLoad:
   def __init__(self,path,mode='rb'):
       self.path = path
       self.mode = mode

   def __enter__(self):
       self.f = open(self.path,self.mode)
       return self

   def loaditer(self):
       while True:
           try:
               ret = pickle.load(self.f)
               yield ret
           except EOFError:
               break

   def __exit__(self, exc_type, exc_val, exc_tb):
       self.f.close()
with MypickelLoad('pickle_file') as mypic:
    for obj in mypic.loaditer():
        print(obj)

在一个函数的前后添加功能

利用使用 装饰器函数中的内容

with语句 就是和 __enter__,__exit__

import time
class Timer:
    def __enter__(self):
        self.start = time.time()
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(time.time() - self.start)

def func():
    print('wahaha')
    time.sleep(1)
    print('qqxing')

with Timer():
    func()
class MypickleDump:
   def __init__(self,path,mode = 'ab'):
       self.path = path
       self.mode = mode

   def __enter__(self):
       self.f = open(self.path,self.mode)
       return self

   def dump(self,obj):
       pickle.dump(obj,self.f)

   def __exit__(self, exc_type, exc_val, exc_tb):
       self.f.close()

with MypickleDump('pickle_file') as obj:
   obj.dump({1,2,3,4})

with MypickelLoad('pickle_file') as obj:
  for i in  obj.loaditer():
      print(i)

重要内置方法

  • __new__
  • __del__
  • __call__
  • __str__
  • __repr__
  • __enter__
  • __exit__

2019-04-02-day024-内置方法的更多相关文章

  1. js-DOM ~ 04. BOM:浏览器对象模型window. 、定时器、在线用户、祝愿墙、BOM的内置方法内置对象

    multiple. select列表多选 触发事件后调用有参数的函数要先创建一个函数,然后在函数内调用执行函数 Array.from(伪数组):伪数组变为真数组 indexOf():查询字符的索引 a ...

  2. 【python基础】第11回 数据类型内置方法 02

    本章内容概要 列表内置方法 字典内置方法 元组内置方法 集合内置方法 可变类型与不可变类型 本章内容详细 1.列表内置方法 list 列表在调用内置方法之后不会产生新的值 1.1 统计列表中的数据值的 ...

  3. python面向对象的基础语法(dir内置函数、self参数、初始化方法、内置方法和属性)

    面相对象基础语法 目标 dir 内置函数 定义简单的类(只包含方法) 方法中的 self 参数 初始化方法 内置方法和属性 01. dir 内置函数(知道) 在 Python 中 对象几乎是无所不在的 ...

  4. s14 第4天 关于python3.0编码 函数式编程 装饰器 列表生成式 生成器 内置方法

    python3 编码默认为unicode,unicode和utf-8都是默认支持中文的. 如果要python3的编码改为utf-8,则或者在一开始就声明全局使用utf-8 #_*_coding:utf ...

  5. day6 六、元组、字典、集合的基本操作和内置方法

    一.元组 1.定义 # 元组tuple # 记录多个值,当值没有改的需求是,建议用元组更好 # 定义:在()内用逗号分开任意类型的值 # name = (, , 300.5]) # print(nam ...

  6. Python_List对象内置方法详解

    目录 目录 前言 软件环境 列表List 修改列表的元素 插入列表元素 extend 将序列中的元素迭代的附加到list中 insert 在指定的索引号中插入一个元素 删除列表元素 del 删除Lis ...

  7. Python_序列对象内置方法详解_String

    目录 目录 前言 软件环境 序列类型 序列的操作方法 索引调用 切片运算符 扩展切片运算符 序列元素的反转 连接操作符 重复运算符 成员关系符 序列内置方法 len 获取序列对象的长度 zip 混合两 ...

  8. [Python3] 009 字符串:给你们看看我的内置方法 第一弹

    目录 前言 如何查看 python3 中和 str 有关的方法 字符串方法 1. capitalize() 2. casefold() 3. center(width) 4. count(sub[, ...

  9. 数据库(十三):MySQL内置方法

    进击のpython ***** 数据库--MySQL内置方法 目录 数据库--MySQL内置方法 视图 增加 修改 删除 触发器 创建 使用 删除 存储过程 无参 有参 事务 代码实现 视图 视图是一 ...

  10. python黑魔法 -- 内置方法使用

    很多pythonic的代码都会用到内置方法,根据自己的经验,罗列一下自己知道的内置方法. __getitem__ __setitem__ __delitem__ 这三个方法是字典类的内置方法,分别对应 ...

随机推荐

  1. IntelliJ IDEA的调试方法

    快捷键F9          resume programe       恢复程序 Alt+F10       show execution point    显示执行断点 F8          S ...

  2. 外网teamview连接不上服务器teamview的错误: 一直显示正在连接,正在初始化显示参数的

    一.错误 错误:  服务器的TV已打开,外网连接服务器TV,一直显示正在连接,正在初始化显示参数的原因. 二. 分析原因: 1. teamview简介TV 2. 服务器必须要开一个远程端口,意思是必须 ...

  3. 『Github』简易使用指南

    一.新建repository 新建项目从下图位置开始, 当我们完成了初始化后,找不到创建/上传文件的位置,只需如下操作, 然后, 即可,当然,按照下图提示进行命令行操作实际是一样的, 创建了READM ...

  4. Spring boot(四)thymeleaf使用介绍

    在上篇文章springboot(二):web综合开发中简单介绍了一下thymeleaf,这篇文章将更加全面详细的介绍thymeleaf的使用.thymeleaf 是新一代的模板引擎,在spring4. ...

  5. python中for循环的底层实现机制 迭代

    在python中,存在2种循环方式:for循环和while循环. while循环的实现很简单, 其本质就是一个条件语句,自定义条件,当条件满足的时候,不断执行while代码块. 但是for循环,究竟是 ...

  6. php自动填充

    1.str_pad() 函数把字符串填充为新的长度. 2.str_pad(string,length,pad_string,pad_type) 参数 描述 string 必需.规定要填充的字符串. l ...

  7. 784. Letter Case Permutation C++字母大小写全排列

    网址:https://leetcode.com/problems/letter-case-permutation/ basic backtracking class Solution { public ...

  8. 关于 EF 对象的创建问题

    在开发过程中,项目往往被划分为多层,而一个请求过来往往是从表示层开始一层一层向下调用,那么如果我们在不同的层中都使用到了 EF 上下文对象,而 有好几层都这么创建一个 EF 对象然后对其进行操作,那么 ...

  9. EF - Database First 开发方式

    概述 Database First 又叫数据库优先的开发方式,是一种比较旧的开发方式,现在越来越多的企业已经不再使用此种开发方式. 当然,对于一些旧项目进行升级,在已经有了数据库的情况下,使用此种方式 ...

  10. 第 3 章 HTML5 网页中的文本和图像

    文字和图像是网页中最主要.最常用的元素. 在互联网高速发展的今天,网站已经成为一个展示与宣传自我的通信工具(公司或个人可以通过网站介绍公司的服务与产品或介绍自己).这些都离不开网站中的网页,而网页的内 ...