资讯专栏INFORMATION COLUMN

python--面向对象进阶

Profeel / 2684人阅读

摘要:它首先被程序语言的设计领域所采用并在和面向对象方面取得了成绩。面向对象中的反射通过字符串的形式操作对象相关的属性。注构造方法的执行是由创建对象触发的,即对象类名而对于方法的执行是由对象后加括号触发的,即对象或者类执行执行逻辑题

isinstance和issubclass

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

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo:
    pass
obj = Foo()
print(isinstance(obj,Foo))

2.issubclass(cls,cls)检查Bar是否是Foo的派生类

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
    pass
class Bar(Foo):
    pass

print(issubclass(Bar,Foo))
反射

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

应用:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
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)
#1.检查是否含有某属性
print(hasattr(obj,"name")) #有该属性返回True
print(hasattr(obj,"six"))  #无该属性返回False
#2.获取该属性
n = getattr(obj,"name")
print(n)
func = getattr(obj,"say_hi")
func()
#3.设置属性
setattr(obj,"sb",True)
setattr(obj,"show_name",lambda self:self.name+"sb")
print(obj.__dict__) #{"name": "egon", "age": 73, "sb": True, "show_name":  at 0x0020C660>}
print(obj.show_name(obj)) #egonsb
#4.删除属性
delattr(obj,"age")
delattr(obj,"show_name")
delattr(obj,"show_name111")#不存在,则报错
print(obj.__dict__)

类也是一种属性

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"))

模块:

import sys
def s1():
    print("s1")
def s2():
    print("s2")
this_module = sys.modules[__name__]

print(hasattr(this_module, "s1")) #True
print(getattr(this_module, "s2")) #
__str__和,__repr__

改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__

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"))
打印结果:
from repr:  School(oldboy1,北京)
from str:  (oldboy1,北京)
(oldboy1,北京)
oldboy1-北京-私立
私立:oldboy1:北京
私立/北京/oldboy1
oldboy1-北京-私立

%s和%r的区别

class B:

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

    def __repr__(self):
        return "repr : class B"
b = B()
print("%s" % b)
print("%r" % b)
#打印结果为:
str : class B
repr : class B
item
__getitem__\__setitem__\__delitem__
class Foo:
    def __init__(self,name):
        self.name=name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print("del obj[key]时,我执行")
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print("del obj.key时,我执行")
        self.__dict__.pop(item)

f1=Foo("sb")
f1["age"]=18
f1["age1"]=19
del f1.age1
del f1["age"]
f1["name"]="alex"
print(f1.__dict__)
__new__
class A:
    def __init__(self):
        self.x = 1
        print("in init function")
    def __new__(cls, *args, **kwargs):
        print("in new function")
        return object.__new__(A, *args, **kwargs)

a = A()
print(a.x)
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()

two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)

单例模式
__call__

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

class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print("__call__")


obj = Foo() # 执行 __init__
obj()       # 执行 __call__
__len__
class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))
__hash__
class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __hash__(self):
        return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
__eq__
class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __eq__(self,obj):
        if  self.a == obj.a and self.b == obj.b:
            return True
a = A()
b = A()
print(a == b)
逻辑题:
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)
obj = list(set(p_lst))[0]
print(obj.name,obj.age,obj.sex)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41983.html

相关文章

  • 学习Python的建议

    摘要:如果初学者接触的第一门语言是,学习曲线则会平滑得多,掌握一些基本语法和内置的数据结构,已经可以上手写一些小工具或者小型应用。如果你的学习时间充足,我的建议是一定要学数据结构和算法。 前言 Python是最容易入门的编程语言,没有之一。如果初学者接触的第一门语言是C或者C++,对他们来说最难的不是语法,而是容易出现内存泄漏、指针等问题。有时候排查这些问题对初学者的打击很大,尤其是没掌握排...

    eechen 评论0 收藏0
  • Python进阶:迭代器与迭代器切片

    摘要:本文是切片系列的第三篇,主要内容是迭代器切片。实际上,迭代器必然是可迭代对象,但可迭代对象不一定是迭代器。这是迭代器切片最具想象力的用途场景。考虑到文件对象天然就是迭代器,我们可以使用迭代器切片先行截取,然后再处理,如此效率将大大地提升。 2018-12-31 更新声明:切片系列文章本是分三篇写成,现已合并成一篇。合并后,修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章...

    hedge_hog 评论0 收藏0
  • Python进阶:迭代器与迭代器切片

    摘要:本文是切片系列的第三篇,主要内容是迭代器切片。实际上,迭代器必然是可迭代对象,但可迭代对象不一定是迭代器。这是迭代器切片最具想象力的用途场景。考虑到文件对象天然就是迭代器,我们可以使用迭代器切片先行截取,然后再处理,如此效率将大大地提升。 2018-12-31 更新声明:切片系列文章本是分三篇写成,现已合并成一篇。合并后,修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章...

    omgdog 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<