类中常用的几种方法:

del()方法
作用:在对象销毁时做一些操作
触发时机:当一个对象在内存中被销毁时自动执行
参数:至少有一个self,接收对象
返回值:无
注意:程序自动执行此方法,不需手动调用

class A():
    count = 0
    def __init__(self,name):
        self.name = name
        A.count += 1
    def __del__(self):
        A.count -= 1
        print("删除{},还剩{}人".format(self.name,A.count))

a = A("李白")
b = A("杜甫")
del a #删除李白,还剩1人
del b #删除杜甫,还剩0人

call()方法
作用:让类的实例具有类似函数的行为
触发时机:在对象后面加括号,触发执行。例如:对象()
参数:可以无
返回值:无
注意:无

class A():
    count = 0
    def __init__(self,name):
        self.name = name
        A.count += 1
    def __call__(self,x):
        print("我被调用了",x)

a = A("李白")
b = A("杜甫")
a(1) #我被调用了 1

利用__call__()方法实现斐波那契数列

class Fib():
    def __init__(self):
        pass
    def __call__(self,num):
        a,b = 1,1
        self.lst = []
        if num == 1:
            self.lst.append(1)
        elif num == 2:
            self.lst.append(1)
            self.lst.append(1)
        else:
            for i in range(2,num + 1):
                self.lst.append(a)
                a,b = b,a + b
        return self.lst
f = Fib()
ret = f(8)
print(ret) #[1, 1, 2, 3, 5, 8, 13]

str()方法
作用:print(对象)时进行操作,得到字符串,通常用于快捷操作
触发时机:使用print(对象)或者str(对象)时触发
参数:一个self接收对象
返回值:必须是字符串类型
注意:无

class Student():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return "我叫{},今年{}岁".format(self.name,self.age)

a = Student("张三",19)
print(a) #我叫张三,今年19岁

repr()方法
作用:改变对象的字符串显示
触发时机:repr()是__str__()的备胎,如果找不到__str__()就会找__repr__()。
参数:%r 默认调用__repr()方法,如果是字符串,会默认加上""
返回值:
注意:%s默认调用__str__()方法

class Student():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return "我叫{},今年{}岁".format(self.name,self.age)
    def __repr__(self):
        return "{},{}岁".format(self.name,self.age)

a = Student("张三",19)
print(a) #我叫张三,今年19岁 #调用__str__()
print("%s"%(a)) #我叫张三,今年19岁
print("%r"%(a)) #张三,19岁

new()方法
作用:实例化对象
触发时机:在实例化时自动触发,如果同时有__new__()方法和__init__()方法,先执行__new__()方法。
参数:至少一个cls接收当前类
返回值:必须返回一个对象实例
注意:

class Student():
    def __new__(cls, *args, **kwargs):
        print("我在new",cls)
        return object.__new__(cls)
    def __init__(self,name):
        print("我在init")
        self.name = name

a = Student("张三")# 我在new <class '__main__.Student'> # 我在init

单例模式

class Student():
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,"inst"):
            cls.inst = object.__new__(cls)
        return cls.inst
    def __init__(self,name):
        self.name = name

a = Student("张三")
b = Student("李四")
print(a == b) #True,比较值是否相等
print(a is b) #True,比较id是否相等
print(a.name) #李四
print(b.name) #李四

init()方法
作用:对对象做一些初始化操作
触发时机:初始化时自动执行
参数:可以无参数

class Cat():
    def __init__(self):
        print("我是初始化方法")
        self.name = "Tom"
cat = Cat()
print(cat.name) #我是初始化方法 Tom
cat2 = Cat()
print(cat2.name) #我是初始化方法 Tom

hash()方法
作用:
触发时机:
参数:
返回值:
注意:
字典中的key必须是可hash的

a = {"a":"b"}
print(a) #{'a': 'b'}
a = {1:"b"}
print(a) #{1: 'b'}
a = {(1):"b"}
print(a) #{1: 'b'}
a = {[a]:"b"}
print(a) #TypeError: unhashable type: 'list'

集合中的元素必须是可hash的

a = {1,2,3,4,[1,2]}
print(a) #TypeError: unhashable type: 'list'

hash()函数默认调用object类的__hash__()方法,hash值是对象id值的1/16

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

a = Student("张三")
b = Student("李四")
c = Student("张三")
d = {a,b,c}
print(d)#{<__main__.Student object at 0x0000000002134320>, <__main__.Student object at 0x00000000022576D8>, <__main__.Student object at 0x00000000022675F8>}
print(hash(a))
print(id(a)/16)

在python中集合要求数据类型是可hash的,因为集合会默认调用对象的__hash__()函数进行快速查询,如果找到了,则调用对象的__eq__()函数,判断两个是否相等,如果相等,则不添加。保证数据的唯一性
自定义对象添加到集合中,两个对象的属性值相同就是同一个对象,因此需要手动复写__hash__()函数,eq()函数

class Student():
    def __init__(self,name):
        self.name = name
    def __eq__(self, other):
        return self.__dict__ == other.__dict__
    def __hash__(self):
        return hash(self.name)
a = Student("张三")
b = Student("李四")
c = Student("张三")
d = {a,b,c}
print(d)
print(hash(a)) #-6622569385845648880
print(hash(b)) #-4951232504155134916
print(hash(c)) #-6622569385845648880

eq()方法

class A():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            return True
        else:
            return False

a = A("张三",19)
b = A("李四",18)
c = A("张三",19)
print(a == b)  #False
print(a == c)  #True
print(id(a)) #43415144
print(id(b)) #43415200


class A():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            print("相等")
            return True
        else:
            return False

a = A("张三",19)
b = A("李四",17)
c = A("张三",19)
lb = []
if a not in lb:
    lb.append(a)
if b not in lb:
    lb.append(b)
if c not in lb:
    lb.append(c)
print(lb) #[<__main__.A object at 0x0000000001D66470>, <__main__.A object at 0x00000000029276A0>]


class A():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            print(self.__dict__)
            return self.__dict__ == other.__dict__
        else:
            return False

a = A("张三",19)
b = A("李四",17)
c = A("张三",19)
lb = []
if a not in lb:
    lb.append(a)
if b not in lb:
    lb.append(b)
if c not in lb:
    lb.append(c)
print(lb) #[<__main__.A object at 0x00000000020B6470>, <__main__.A object at 0x00000000029476A0>]


a = "123"
b = hash(a)
print(b)

is 和 == 的区别
is:比较两个对象的内存地址是否相等
==:比较两个对象的内容是否相等

a = [1,2,3]
b = [1,2,3]
print(a == b) #True
print(a is b) #False
print(id(a),id(b)) #30237256 30237320

类中常用的几种函数:
issubclass()
作用:判断一个类是否是另一个类的子类
格式:issubclass(被判断的类,(父类1,父类2,父类3…))
返回值:布尔值
注意:只要有一个类是被检查类的父类,那么最终结果就是True

class A():
    pass
class B(A):
    pass
class C():
    pass
print(issubclass(B,A)) #True
print(issubclass(C,A)) #False

isinstance()
作用:判断一个对象是否是某个类的对象
格式:isinstance(对象,(类1,类2,类3…))
返回值:布尔值
注意:只要有一个类是被检查对象的类,那么最终结果就是True

class A():
    pass
class B(A):
    pass
class C():
    pass
a = A()
c = C()
print(isinstance(a,A)) #True
print(isinstance(c,A)) #False

反射方法:
python面向对象中的反射:通过字符串的形式,操作对象相关的属性
python中的一切事物都是对象,都可以使用反射

hasattr()
作用:判断对象/类是否具有某个属性
格式:hasattr(对象/类,“属性名”)
返回值:布尔值

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

a = Student("张三")
b = hasattr(a,"name")          #判断对象是否有某个属性
c = hasattr(a,"age")           #判断对象是否有某个属性
print(b)                        #True
print(c)                        #False
a.age = 19                      #添加对象属性
d = hasattr(a,"age")           #判断对象是否有某个属性
print(d)                        #True
if not hasattr(a,"age"):       #结果为False
    print("a没有age属性")      #不输出
if hasattr(a,"age"):           #结果为True
    print("a有age属性")        #a有age属性
e = hasattr(Student,"count")    #判断类中是否有某个属性
print(e)                         #True
if not hasattr(Student,"Tax"):  #结果为True
    print("没有")               #没有
    Student.Tax = 0.1            #添加类属性
f = hasattr(Student,"Tax")      #判断类中是否有某个属性
print(f)                         #True

根据用户输入的key来调用相应的方法

class A():
    dic = {"查看学生信息":"func1","查看老师信息":"func2"}
    def func1(self):
        print("学生信息")
    def func2(self):
        print("老师信息")
func = input("请输入")
a = A()
if hasattr(a,a.dic.get(func)):
    f = getattr(a,a.dic[func])
    f()
else:
    print("无此功能")

getattr()
作用:获取对象/类的成员值
格式:getattr(对象/类,“属性名”,成员不存在时的默认值(可以不设置此参数))
返回值:成员的值

class Teacher():
    #类的静态属性
    dic = {"name":"hehe","age":18}
    def __init__(self,name,age):
        self.name = name
        self.age = age
    #类方法
    @classmethod
    def func1(cls):
        print("呵呵")
    def func2(self):
        print("哈哈")
a = Teacher("张三",49)
b = getattr(Teacher,"dic")   #获取类的静态属性
print(b) #{'name': 'hehe', 'age': 18}

c = getattr(a,"name")        #获取对象属性
print(c) #张三

d = getattr(Teacher,"func1") #获取类方法
d() #呵呵
e = Teacher("张三",39)
f = getattr(e,"func2")       #获取对象方法
f() #哈哈

setattr()
作用:添加或设置对象/类的属性
格式:setattr(对象/类,“属性名”,值)
返回值:无

class A():
    pass

setattr(A,"count",100) #添加类属性
print(A.count) #100
a = A()
setattr(a,"num",200)   #添加对象属性
print(a.num) #200

delattr()
作用:删除对象/类中的某个属性
格式:delattr(对象/类,“属性名”)
返回值:无

class A():
    Tax = 100
    def __init__(self,name,age):
        self.name = name
        self.age = age

a = A("张三",19)
print(A.Tax)  #100
delattr(A,"Tax") #删除类中的某个属性
print(A.Tax)  #AttributeError: type object 'A' has no attribute 'Tax'

print(a.name)  #张三
delattr(a,"name") #删除对象中的某个属性
print(a.name)  #AttributeError: 'A' object has no attribute 'name'

反射导入模块中的属性、函数、类
格式:getattr(模块名,“属性/函数/类”)

import one1_module                 #我不是主函数 one1_module
a = getattr(one1_module,"day")     #反射导入模块中的属性
print(a)                           #星期五
b = getattr(one1_module,"func")   #反射导入模块中的函数
b()                                #嘿嘿,快放假了
c = getattr(one1_module,"A")       #反射导入模块中的类
c()                                #哈哈

反射自己模块中的属性、函数
借助sys模块获取当前模块的名称

import sys
print(sys.modules) #查看所有模块
print(sys.modules["__main__"]) #<module '__main__' from 'D:/python第一阶段/05.07.py'>
a = 123456
b = getattr(sys.modules["__main__"],"a")   #获取当前模块中的属性
print(b) #123456

def func():
    print("哈哈")
c = getattr(sys.modules["__main__"],"func") #获取当前模块中的函数
c()

反射内置模块

import time
print(time.time())
print(time.sleep(2))

a = getattr(time,"sleep") #获取内置模块的函数
a(2)
print("abc")
b = getattr(time,"time")   #获取内置模块的属性
print(b())

作业

1、魔术方法 __del__练习

class ReadFile:

    # 打开文件(构造)
    def __init__(self, filename):
        # 打开文件将文件io对象保存在对象成员
        self.fp = open(filename, 'r')

    # 读取文件
    def fread(self):
        return self.fp.read()

    # 关闭文件(析构)
    def __del__(self):
        print('关闭文件操作')
        self.fp.close()


import os

one = ReadFile(os.getcwd() + "\\aa.txt")
txt = one.fread()
print(txt)

2、魔术方法 eq 方法练习

class Myint(int):
    def __eq__(self, other):
        if self % 6 == 0 and other % 6 == 0:
            return True
        else:
            return False

a = Myint(6)
b = Myint(12)

c = a == b
print(c) #True

3、魔术方法 hash 和 __eq__练习
设计二维坐标类Point,比较2个坐标是否相等?

class Point(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __hash__(self):
        return hash((self.x,self.y))
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

a = Point(1,2)
b = Point(1,2)
print(hash(a)) #3713081631934410656
print(hash(b)) #3713081631934410656
print(id(a))   #43284184
print(id(b))   #49388960
print(a is b)  #False
print(a == b)  #True