day 24 内置函数(补充)

 

一。 内置函数 
1.__len__ 与 len()


# class A:
# def __init__(self,name,age,sex,cls):
# self.name = name
# self.age = age
# self.sex = sex
# self.cls = cls
# def __len__(self):
# return len(self.__dict__)
#
# # 有一个内置函数 和内置方法len()是唯一对应的关系
# a1 = A('alex',81,'不详',2)
# a1.hobby = '烫头'
# a2 = A('egon',20,'不详',3)
# a3 = A('yuan',21,'不详',4)
# print(len(a1))
# print(len(a2))
# print(len(a3))



2.
字典的存储
# hash

class A:
def __init__(self,name,age,sex,cls):
self.name = name
self.age = age
self.sex = sex
self.cls = cls
def __hash__(self):
return 0
a1 = A('alex',81,'不详',2)
print(hash(a1))
每一次的哈希值都不同,为什么可以直接哈希,因为object类里有__hash__方法
 

 

二。__str__ 与 __repr__  与  print()

ps: 总结:

  1.print() 想文件中写,print() 替你将数据类型转化成字符串打印出来

  2.__str__ :  object 类中的__str__ 就是返回一个数据类型的内存地址

 

l = [1,2,3,4]
print(l)   # 向文件中写   print替你将数据类型转化成字符串打印出来

class List:
    def __init__(self,*args): 5
        self.l = list(args)
    def __str__(self):
        return '[%s]'%(','.join([str(i) for i in self.l]))
l = List(1,2,3,4,5)
print(l)   #--> l.__str__()   # object类中的__str__就是返回一个数据的内存地址
print(l)
print(str(l))
print('%s'%l)
print(obj)   的结果 是 obj.__str__()的结果
str(obj)   的结果 也是 obj.__str__()的结果
'%s'%obj   的结果 也是 obj.__str__()的结果

 

 

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

    # def __str__(self):
    #     return "Teacher's object is %s" %self.name
    def __repr__(self):
        return "repr %s" %self.name
a = Teacher('alex',18)
b = Teacher('wusir',18)

print(a)
print(repr(b))
# repr(obj)的结果和obj.__repr__()是一样的
# '%r'%(obj)的结果和obj.__repr__()是一样的

总结:

  1.实际上上述三种结果都是__str__的返回值

  2.当然:如果我们不手动改写object中 的上下划线str或者repr,就会默认调用object类中的方法,默认返回的是 内存地址

 

思考:why? repr(1)  与 repr('1'):的打印结果不同?

因为:在整形中 定义的repr方法,与在str中定义的repr方法定义的函数方法的返回值不同。  即在class int 与 class str 中的 __repr__ 方法的返回值不同

 

class Teacher:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return "Teacher's object %s"%self.name
    def __repr__(self):
        return 'repr function %s'%self.name
a = Teacher('alex',80)
b = Teacher('egon',80)
print(a)
print(b)

PS:总结:

  1.到需要使用__str__的方法时,找不到__str__方法时,就会找__repr__方法。

  2.当需要使用__repr__的方法时,找不到__repr__的方法时,就会找父类的或object的__repr__方法,这是默认返回的时内存地址

  3.repr()方法是 str()方法的备胎。嘿嘿嘿(偷笑)

  3.实际上:len()和 repr() 方法的返回值都是依赖__len__和__repr__方法来返回值的

三。__len__方法 与 __hash__方法

# class A:
# def __init__(self):pass
# def __len__(self):pass
# def len(obj):
# obj.__len__()
# a = A()
# a.__len__()
# len() # 为什么要归一化设计呢?
# 更接近面向函数编程,简单且节省代码

# len()  obj.__len__()  返回值是一致的
# len() 的结果是依赖 obj.__len__()
# hash() 的结果是依赖 obj.__hash__()

# str() 的结果是依赖 obj.__str__()
# print(obj) 的结果是依赖 obj.__str__()
# %s 的结果是依赖 obj.__str__() # 语法糖
#
# repr() 的结果是依赖 obj.__repr__()
# %r 的结果是依赖 obj.__repr__()
# repr是str的备胎
思考:如果str与repr 我只能实现一个,那选哪个?# __str__
# __repr__   一定是选择repr


什么是语法糖?语法糖的定义?
  
  答:语法糖就是可以让数据结构变得更加简单,就像吃了糖一样甜。这就是语法糖。

四。__format__方法?
  
class Format:
    def __init__(self,name,age,hobby):
        self.name = name
        self.age = age
        self.hobby = hobby

    def __format__(self,format_spec):
        return format_spec.format(obj = self)

person = Format('alex',18,'')
format_spec = '{obj.name}-{obj.age}-{obj.hobby}'
print(format(person,format_spec))

 

五:__call__?

 

class Teacher:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __call__(self):
        print(123)


t = Teacher('wusir',18)
t()

靠?方法加(),什么鬼?  

 

对象名()   相当于调用了类内置的__call__方法

print(callable(类名)):是否可调用的

如果一个对象是否可调用,取决于这个对象对应的类是否有__call__方法


2.__eq__?
class A:pass
a = A()
b = A()
print(a == b)

返回False
因为连个对象的内存地址是不一样的,
# class A:
#     def __eq__(self, other):
#         # if self.__dict__ == other.__dict__:
#             return True
# # __eq__()
# a = A()
# a.name = 'alex'
# b = A()
# b.name = 'egon'
# print(a)
# print(b)
# print(a == b)

# == 是由__eq__的返回值来决定的

# == 是由__eq__的返回值来决定的

 

3.__del__ 析构方法?

在删除一个对象的时候做一些收尾工作。

 

class A:
    def __init__(self):
        self.f = open('文件','w')

a = A()
print('aaa')

 

把a对象删除不用了

这是文件并没有关闭,文件没有关闭会占内存。

应该在删除对象是进行一个析构方法,用操作系统将文件关闭在删除文件

 

class A:
    def __init__(self):
        pass
        self.f = open('文件','w')
    def __del__(self):
        self.f.close()
        print('执行我了')

a = A()
del a
print(a)
print('aaa')

 

4.__new__?

__new__  构造方法

实例化对象的时候

创建对象的过程

init  初始化

   设计模式 —— 单例模式

 单例模式 就是 一个类 只能有一个实例
# class A:pass
# a = A()
# b = A()
# print(a)
# print(b)

# class B:
#     __instance = None
#     def __new__(cls, *args, **kwargs):
#         if cls.__instance is None:
#             obj = object.__new__(cls)
#             cls.__instance = obj
#         return cls.__instance
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#     def func(self):
#         print(self.name)
# a = B('alex',80)
# b = B('egon',20)
# print(a)
# print(b)
# print(a.name)
# print(b.name)

 




5.__item__系列
# item
# dic = {'k':'v'}
# print(dic['k'])


# class Foo:
#     def __init__(self,name):
#         self.name=name
#
#     def __getitem__(self,item):
#         return  self.__dict__[item]
#
#     def __setitem__(self, key, value):
#         self.__dict__[key]=value
#
#     def __delitem__(self, key):
#         print('del obj[key]时,我执行')
#         self.__dict__.pop(key)

# f = Foo('alex')
# # f.name = ...
# print(f['name'])    # f.__getitem__('name')
# f['age']  = 18      # 赋值
# print(f.age)         # 自带的语法
# print(f['age'])     # 修改
# f['age']  = 80
# print(f['age'])     # 通过实现__getitem__得到的
# del f['age']
# print(f.age)         # 删除

# class Foo:
#     def __init__(self,name):
#         self.name=name
#     def __delattr__(self, item):
#         print('del obj.key时,我执行')
#         self.__dict__.pop(item)
# f = Foo('alex')
# del f.name     #相当于执行了__delattr__
# # delattr(f,'name')

 

面试题:  

# 写一个类 定义100个对象
# 拥有三个属性 name age sex
# 如果两个对象的name 和 sex完全相同
# 我们就认为这是一个对象
# 忽略age属性
# 做这100个对象的去重工作
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __hash__(self):
# hash算法本身就存在了 且直接在python中就能调用
# 姓名相同 性别相同的对象的hash值应该相等才行
# 姓名性别都是字符串
return hash(self.name+self.sex)
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:
return True
# python2.7
# 去重 set
# hash方法
# set([obj,obj]) unhashable
# hash算法 一个值 进行一系列的计算得出一个数字在一次程序执行中总是不变
#来让每一个不同的值计算出的数字都不相等
obj_lst = []
obj_lst.append(Person('alex',80,'male'))
obj_lst.append(Person('alex',70,'male'))
obj_lst.append(Person('alex',60,'male'))
obj_lst.append(Person('boss_jin',50,'male'))
obj_lst.append(Person('boss_jin',40,'male'))
obj_lst.append(Person('boss_jin',30,'male'))
obj_lst.append(Person('nezha',20,'male'))
obj_lst.append(Person('nezha',10,'male'))
obj_lst = set(obj_lst)
for obj in obj_lst:print(obj.name)
# set对一个对象序列的去重 依赖于这个对象的两个方法 hash eq


# 可hash顺带着写的
# eq来做判断

# key hash 数字 --》 内存地址 --》 value
# set hash 数字 --》 内存地址 --》 set中的元素
# 'aaa' hash

# java
# set去重 一个容器中 有相同值的内容 __eq__
# 当你这个容器中有10000个元素的时候 我判断第10000个元素
# hash算法
# 'abc'
# 'bca'
# set对一个对象序列的去重 如何判断这两个值是否相等
# 值a进行hash --> 存值
# 值b进行hash --> 判断值是否相等 -相等-> 说明是一样的
#-不相等-> 在开辟一个空间 来存放b

 








 

 

 

 

 

  

posted @ 2018-04-19 17:13  Coca-Mirinda  阅读(159)  评论(0编辑  收藏  举报