python -- 面向对象进阶

时间:2023-02-15 13:41:25

1, classmethob

1,在类中定义一个类方法

  如果你的整个方法中都没有用到对象命名空间中的名字,且你用到了类的命名空间中的名字(普通方法和property方法除外)

class Goods:
    __discount = 0.8 # 静态属性
    def __init__(self,price):
        self.__price = price  # 对象属性
        self.name = "apple"
    @property
    def prince(self):
        print(self)  # <__main__.Goods object at 0x036B0710>
        return self.__price * Goods.__discount
    @classmethod
    def change_discount(cls,new):  # 类方法
        cls.__discount = new
        
obj = Goods(10)
print(obj.prince)

Goods.change_discount(0.7)
print(Goods.__dict__)

类方法的默认参数 : cls 值得是调用这个方法的类
类方法的调用方式 : 通过类名调用,本质是方法

 

2,staticmethod

将一个普通的函数放到类中来就给这个函数加上一个@staticmethod装饰器
这个函数就不需要传默认的参数:self,cls

class Foo:
    @classmethod
    def class_methob(cls):
        pass
    @staticmethod
    def stati_methob():
        pass
from types import MethodType,FunctionType
obj = Foo()

print(isinstance(Foo.class_methob,MethodType) # 判断是否是方法
print(isinstance(Foo.stati_methob,FunctionType)) # 判断是否是函数
print(obj.stati_methob)  # <function Foo.stati_methob at 0x050A5030>

# isinstance 判断对象和类之间的关系
# 判断这个对象是否是这个类、这个类的子类的对象

# issubclass 判断类和类之间的关系
# 判断一个类是否是另一个类的子类

静态方法的调用方式 : 通过类名调用,本质还是函数

 

类方法总结:

 
 

类方法 的 特点
# 只使用类中的资源,且这个资源可以直接用类名引用的使用,那这个方法应该被改为一个类方法

类:
    # 静态属性         类  所有的对象都统一拥有的属性
    # 类方法           类  如果这个方法涉及到操作静态属性、类方法、静态方法                            cls 表示类
    # 静态方法         类  普通方法,不使用类中的命名空间也不使用对象的命名空间   : 一个普通的函数    没有默认参数
    # 方法             对象                                                                            self 表示对象
    # property方法     对象 

 

3,isinstance 和type 区别 

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

python -- 面向对象进阶python -- 面向对象进阶
# print(type(123) is int)
# print(isinstance(123,int))

# class A:
#     pass
# class B(A):
#     pass
# a = A()
# b = B()

# print(type(a) is A)
# print(type(b) is A)
# print(type(b) is A)

# print(isinstance(a,A))
# print(isinstance(b,A))
# print(isinstance(a,B))
区别

内置的 type() 函数可以用来查询变量所指的对象类型。

>>> a, b, c, d = 20, 5.5, True, 4+3j
>>> print(type(a), type(b), type(c), type(d))
<class 'int'> <class 'float'> <class 'bool'> <class 'complex'>

此外还可以用 isinstance 来判断:

>>>a = 111
>>> isinstance(a, int)
True

但是在判断继承的关系的时候,二者判断结果会有所不同:

python -- 面向对象进阶python -- 面向对象进阶
class A:
    pass
 
class B(A):
    pass
 
isinstance(A(), A)  # returns True
type(A()) == A      # returns True
isinstance(B(), A)    # returns True
type(B()) == A        # returns False
View Code

区别就是:

  • type()不会认为子类是一种父类类型。
  • isinstance()会认为子类是一种父类类型。

 

4,issubclass

issubclass(sub, super)检查sub类是否是 super 类的派生类 

将一个普通的函数放到类中来就给这个函数加上一个@staticmethod装饰器
这个函数就不需要传默认的参数:self,cls

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

print(issubclass(B,A)) # False
# 检测类与类之间的关系

静态方法的调用方式 : 通过类名调用,本质还是函数

 

5,反射

python -- 面向对象进阶python -- 面向对象进阶
# what 是什么
    # 反射 使用字符串数据类型的变量名来获取这个变量的值
# a = 1
# b = 2
# name = 'alex'

# why 为什么 三个场景
    # input
        # 用户输入的如果是a,那么就打印1,如果输入的是b就打印2,如果输入的是name,就打印alex
    # 文件
        # 从文件中读出的字符串,想转换成变量的名字
    # 网络
        # 将网络传输的字符串转换成变量的名字
# where 在哪儿用
# how 怎么用
3w 1h

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

 

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

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

python -- 面向对象进阶python -- 面向对象进阶
def hasattr(*args, **kwargs): # real signature unknown
    """
    Return whether the object has an attribute with the given name.
    
    This is done by calling getattr(obj, name) and catching AttributeError.
    """
    pass
hasattr
python -- 面向对象进阶python -- 面向对象进阶
def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass
getattr
python -- 面向对象进阶python -- 面向对象进阶
def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass
setattr
python -- 面向对象进阶python -- 面向对象进阶
def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.
    
    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass
delattr
python -- 面向对象进阶python -- 面向对象进阶
class Foo:
    f = '类的静态变量'
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def say_hi(self):
        print('hi,%s'%self.name)

obj=Foo('egon',73)

#检测是否含有某属性
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))

#获取属性
n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()

print(getattr(obj,'aaaaaaaa','不存在啊')) #报错

#设置属性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))

#删除属性
delattr(obj,'age')
delattr(obj,'show_name')
delattr(obj,'show_name111')#不存在,则报错

print(obj.__dict__)
四个方法的使用演示

 

python -- 面向对象进阶python -- 面向对象进阶
class Foo(object):
 
    staticField = "old boy"
 
    def __init__(self):
        self.name = 'wupeiqi'
 
    def func(self):
        return 'func'
 
    @staticmethod
    def bar():
        return 'bar'
 
print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')
类也是对象

 

python -- 面向对象进阶python -- 面向对象进阶
import sys


def s1():
    print 's1'


def s2():
    print 's2'


this_module = sys.modules[__name__]

hasattr(this_module, 's1')
getattr(this_module, 's2')
反射当前模块成员

导入其他模块,利用反射查找该模块是否存在某个方法

python -- 面向对象进阶python -- 面向对象进阶
def test():
    print('from the test')

"""
程序目录:
    module_test.py
    index.py
 
当前文件:
    index.py
"""

import module_test as obj

#obj.test()

print(hasattr(obj,'test'))

getattr(obj,'test')()
View Code

 

__str__ 和 __repr__

改变对象的字符串显示__str__,__repr__

自定制格式化字符串__format__

python -- 面向对象进阶python -- 面向对象进阶
format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type

    def __repr__(self):
        return 'School(%s,%s)' %(self.name,self.addr)
    def __str__(self):
        return '(%s,%s)' %(self.name,self.addr)

    def __format__(self, format_spec):
        # if format_spec
        if not format_spec or format_spec not in format_dict:
            format_spec='nat'
        fmt=format_dict[format_spec]
        return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)

'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
View Code
python -- 面向对象进阶python -- 面向对象进阶
class B:

     def __str__(self):
         return 'str : class B'

     def __repr__(self):
         return 'repr : class B'


b=B()
print('%s'%b)
print('%r'%b)
%s和%r