python之面向对象进阶3

时间:2022-09-02 22:47:14

1.isinstace和issubclass

2.staticmethod和classmethod

3.反射(hasattr、getattr、setattr.delattr等四个方法)

4.内置方法

1.isinstace和issubclass 

isinstace判断一个对象是否是一个类的对象。与type的区别;判断对象类型时一定要用type。

class Foo:
pass

class Son(Foo):
pass

s
= Son()
#判断一个对象是不是这个类的对象,传两个参数(对象,类)
print(isinstance(s,Son))
print(isinstance(s,Foo))
# print(type(s) is Son)
#
print(type(s) is Foo)

 

issubclass判断一个类是不是另一个类的子类。

class Foo:
pass

class Son(Foo):
pass

s
= Son()


#判断一个类是不是另一类的子类,传两个参数(子类,父类)
#
print(issubclass(Son,Foo))
#
print(issubclass(Son,object))
#
print(issubclass(Foo,object))
#
print(issubclass(int,object))

 

2.@staticmethod 和@classmthod

@staticmetho(静态方法)  没有默认参数让类里的方法直接被调用,就像正常函数一样。(可以被类和对象调用,不推荐用对象调)

class Student:
f
= open('student', encoding='utf-8')
def __init__(self):
pass

def func(self):
pass
@staticmethod
#静态方法 : 让类里的方法直接被类调用,就像正常的函数一样
def show_student_info_static():
f
= open('student', encoding='utf-8')
for line in f:
name, sex
= line.strip().split(',')
print(name, sex)
s
=Student()
s.show_student_info_static()
print(Student.show_student_info_static)

 

 

@classmethod(类方法)          默认参数是cls,可以直接使用类和对象调用,不推荐用对象调。

class Student:
f
= open('student', encoding='utf-8')
def __init__(self):
pass

def func(self):
pass

@classmethod
#类方法:默认参数cls,可以直接用类名调用,可以与类属性交互
def show_student_info_class(cls):
for line in cls.f:
name, sex
= line.strip().split(',')
print(name, sex)

s
=Student()
s.show_student_info_class()
print(Student.show_student_info_class)

总结:

#classmethod和staticmethod
#
相同:都可以直接被类调用,不需要实例化
#
不同:
#
类方法必须有一个cls参数表示这个类,可以使用类属性
#
静态方法不需要,静态方法不能直接使用

#绑定方法
#
非绑定方法

#普通方法 默认有一个self对象传进来,并且只能被对象调用——绑定到对象
#
类方法 默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类
#
静态方法 没有默认参数,并且可以被类和对象(不推荐)调用——非绑定
#classmethod和staticmethod
#
相同:都可以直接被类调用,不需要实例化
#
不同:
#
类方法必须有一个cls参数表示这个类,可以使用类属性
#
静态方法不需要,静态方法不能直接使用

#绑定方法
#
非绑定方法

#普通方法 默认有一个self对象传进来,并且只能被对象调用——绑定到对象
#
类方法 默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类
#
静态方法 没有默认参数,并且可以被类和对象(不推荐)调用——非绑定

 

3.反射(常用:hasattr、getattr;不常用:setattr、delattr)(通过字符串的形式来访问对象的属性与调用对象的方法)(应用范围为 对象、类、模块)

hasattr与getattr:

class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
print(hasattr(egg,'name'))#返回bool
print(getattr(egg,'name'))
if hasattr(egg,'func'): #返回bool
Foo_func = getattr(egg,'func') #如果存在这个方法或者属性,就返回属性值或者方法的内存地址
#如果不存在,报错,因此要配合hasattr使用
Foo_func()#执行func方法

不常用的setattr与delattr

class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()

def show_name(self):
print(self.name + ' sb')
setattr(egg,
'sh_name',show_name)#新增一个方法
#
egg.sh_name(egg)#新增方法调用时要传参数就是对象自己
#
show_name(egg)#通过函数调用
class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
# delattr
delattr(egg,'name')
print(egg.name)

反射的延伸:(类也是对象)

我们一般用hasattr判断是否有这个属性或方法,用getattr方法调用这个属性或者方法
class Foo:
f
= 123 #类变量
@classmethod#类方法
def class_method_demo(cls):
print('class_method_demo')
@staticmethod
#静态方法
def static_method_demo():
print('static_method_demo')
if hasattr(Foo,'f'):#类属性
print(getattr(Foo,'f'))
print(hasattr(Foo,'class_method_demo'))
method
= getattr(Foo,'class_method_demo')
method()
print(hasattr(Foo,'static_method_demo'))
method2
= getattr(Foo,'static_method_demo')
method2()
#类也是对象

模块使用反射分为引入模块与本类模块

引入模块:

import my_module
print(hasattr(my_module,'test'))
# func_test = getattr(my_module,'test')
#
func_test()
getattr(my_module,'test')()

在本模块中的使用

def demo1():
print('喜欢你')

import sys
# print(__name__) #'__main__'
#
print(sys.modules)
#
'__main__': <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'>
module_obj =sys.modules[__name__] #sys.modules['__main__']
#
module_obj : <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'>
#
print(module_obj)
print(hasattr(module_obj,'demo1'))
getattr(module_obj,
'demo1')()
#在本模块中应用反射

4内置方法

(str与repr)

class Foo:
def __init__(self,name):
self.name
= name
# def __str__(self):
# return '%s obj info in str'%self.name
def __repr__(self):
return ' obj info in repr'# f = Foo('egon')
#
print(f)
#
print('%s'%f)
#
print('%r'%f)
#
print(repr(f)) # f.__repr__()
#
print(str(f))
#
当打印一个对象的时候,如果实现了str,打印返回值
#
当str没有被实现的时候,就会调用repr方法
#
但是当你用字符串格式化的时候 %s和%r会分别去调用__str__和__repr__
#
不管是在字符串格式化的时候还是在打印对象的时候,repr方法都可以作为str方法的替补
#
但反之不行
#
用于友好的表示对象。如果str和repr方法你只能实现一个:先实现repr

del方法

class Foo:
def __del__(self):
print('执行我啦')

f
= Foo()
print(123)
print(123)
print('..........')
print(123)
print(123)
print(123)

__new__方法

class A:
def __init__(self): #在执行__init__方法有一个方法在帮你创造self
print('in init function')
self.x
= 1

def __new__(cls, *args, **kwargs):#先执行__new__方法
print('in new function')
return object.__new__(A, *args, **kwargs)
a
= A()
b
= A()
c
= A()
d
= A()

 

单例模式

class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance
= object.__new__(cls, *args, **kw)
return cls._instance

one
= Singleton()
two
= Singleton()
print(one,two)
one.name
= 'alex'
print(two.name)

__call__方法

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:
def __call__(self, *args, **kwargs):
print(123)

Foo()()

__len__

class Foo:
def __len__(self):
return len(self.__dict__)
def __hash__(self):
print('my hash func')
return hash(self.name)
f
= Foo()
print(len(f))
f.name
= 'egon'
print(len(f))
print(hash(f))

__hash__与__eq__

#留下同样名字和性别的对象
class Person:
def __init__(self,name,age,sex):
self.name
= name
self.age
= age
self.sex
= sex

def __hash__(self):
return hash(self.name+self.sex)

def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:
return True

p_lst
= []
for i in range(84):
p_lst.append(Person(
'egon',i,'male'))
print(p_lst)
print(set(p_lst))

纸牌游戏

from collections import namedtuple
Card
= namedtuple('Card',['rank','suit']) #每一个card的对象就是一张纸牌

class FranchDeck:
ranks
= [str(n) for n in range(2,11)] + list('JQKA')
suits
= ['红心','方板','梅花','黑桃']

def __init__(self):
self._cards
= [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suits]

def __len__(self):
return len(self._cards)

def __getitem__(self, item):
return self._cards[item]

def __setitem__(self, key, value):
self._cards[key]
= value

def __call__(self, *args, **kwargs):
return self._cards

deck
= FranchDeck()
print(deck[0])
print(deck[3])
print(deck[2])
print(deck[1])
# from random import shuffle   #shuffle可以打乱顺序
# shuffle(deck)#洗牌
# print(deck())
# shuffle(deck)
# print(deck())#洗牌