Python - - 面向对象 - - 面向对象进阶

目录

  • isinstance和issubclass
  • 反射
    • setattr
    • delattr
    • getattr
    • hasattr
  • __str__和repr
  • del
  • item系列

      - getitem

      - setitem

      - delitem

  • new
  • call
  • len
  • hash
  • eq

1 isinstance和issubclass

  • isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class A:pass
a = A()
print(isinstance(a, A))

# 结果呈现
True
  • issubclass(sub, super)检查sub类是否是 super 类的派生类
class A:pass
class B(A):pass
print(issubclass(B, A))
print(issubclass(A, B))

# 结果呈现
True
False

2 反射

  • 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
  • python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
  • 四个可以实现自省的函数,下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
  • hasattr

`````

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

- getattr

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

- setattr

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

- delattr

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

- 四个方法的使用演示

反射:是用字符串类型的名字 去获取 变量

name = 1

eval("print(name)") # 安全隐患

反射:没有安全问题

反射对象中的属性和方法

class A:

def func(self):

print("in func")

a = A()

a.name = "alex"

反射对象的属性

ret = getattr(a,"name") # 通过变量名的字符串形式取到的值

print(ret)

print(a.__dict__)

variable_name = input(">>>")

print(getattr(a, variable_name))

print(a.__dict__[variable_name])

class A:

def func(self):

print("in func")

a = A()

a.name = "alex"

反射对象的方法

a.func()

ret = getattr(a,"func")

ret()

class A:

price = 20

@classmethod

def func(cls):

print("in func")

反射类的属性

A.price

print(getattr(A,"price"))

反射类的方法: classmethod staticmethod

A.func()

if hasattr(A,"func"):

getattr(A, "func")()

模块

import test_project.my_module_obj

反射模块的属性

print(getattr(test_project.my_module_obj,"day"))

反射模块的方法

getattr(test_project.my_module_obj,"wahaha")()

内置模块

def qqxing():

print("qqxing")

year = 2018

import sys

print(sys.modules["main"].year)

反射自己模块中的变量

print(getattr(sys.modules["main"],"year"))

反射自己模块中的函数

getattr(sys.modules["main"],"qqxing")()

varible_name = input(">>>")

print(getattr(sys.modules["main"], varible_name))

print(getattr(sys.modules[name], varible_name))

要反射的函数有参数怎么办

import time

print(time.strftime("%Y-%m-%d %H:%M:%S"))

print(getattr(time, "strftime")("%Y-%m-%d %H:%M:%S"))

一个模块中的类能不能反射得到

import test_project.my_module_obj

print(getattr(test_project.my_module_obj,"C")())

setattr 设置修改变量

class A:

pass

a = A()

setattr(A,"name","alex")

setattr(a,"name","nezha")

print(A.name)

print(a.name)

delattr()

delattr(a,"name")

print(a.name)

delattr(A,"name")

print(A.name)

my_module_obj.py

day = "Monday" # 周一

def wahaha():

print("wahahaha")

class C:

pass


## 3 __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(‘myschool‘,‘北京‘,‘私立‘)

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

class A:

def str(self):

return "A‘s object"

def func(self):

return "wahaha"

a = A()

print(str(a)) # a.__str__ --> object

print(a) # 答应一个对象的时候,就是调用a.__str__

object 里有一个 str, 一旦被调用,就返回调用这个方法的对象的内存地址

lst = [1, 2, 3, 4, 5] # 实例化一个列表类的对象

print(lst)

print(‘%s:%s‘ % ("A", a))

%s str() 直接打印实际上调的都是 str

class Teacher:

def init(self, name, salary):

self.name = name

self.salary = salary

def str(self):

return "Teacher‘s object : %s" % self.name

def repr(self):

return str(self.__dict__)

def func(self):

return "wahaha"

nezha = Teacher("哪吒", 250)

print(nezha)

print(repr(nezha))

print(">>> %r" % nezha)

-  %r repr() 实际上调的是 __repr__
- repr 是 str 的备胎,但str不能做repr的备胎
- print(obj) / ‘%s‘%obj / str(obj)的时候,实际上是内部调用了 obj.__str__方法,如果str方法有,那么它返回的必定是一个str数据类型
- 如果没有__str__方法,会先找本类中的 __repr__方法,再没有再找父类的 __str__
- repr(),只会找 __repr__, 如果没有找父类的 __repr__

## 4 __del__
- 析构方法,当对象在内存中被释放时,自动触发执行。
- 注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class A:

def del(self): # 析构函数:在删除一个对象前进行一些收尾工作

print("执行我啦")

a = A()

del a # del 先执行了这个方法,又删除了变量 - - 执行我啦

print(a) # NameError: name ‘a‘ is not defined

结果呈现

执行我啦

File "C:/Users/thinkpad/Envs/daily_test/test_project/面向对象.py", line 1435, in

引用计数

class A:

def del(self): # 析构函数:在删除一个对象前进行一些收尾工作

print("执行我啦")

a = A()

import time

time.sleep(3) # 执行了del 方法 - - 执行我啦

结果呈现

执行我啦

class A:

def del(self): # 析构函数

self.f.close() # 在 a.f 在内存中消失前,先关闭打开的文件

a = A()

a.f = open() # 打开文件 ,在操作系统中打开了一个文件,拿到了文件操作符存在了内存中

del a # 删除 a 以后,a.f 拿到了的文件操作符也消失在内存中


## 5 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__)


## 6 __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)


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

class A:

def init(self,name):

self.name = name

def call(self, *args, **kwargs):

"""

打印这个对象中的所有属性

:param args:

:param kwargs:

:return:

"""

print("执行我啦")

    for k in self.__dict__:
        print(k,self.__dict__[k])

a = A("alex")

a()

等同于

a = A("alex")()

结果呈现

执行我啦

name alex

执行我啦

name alex


## 8 __len__

class Classes:

def init(self, name):

self.name = name

self.student = []

def len(self):

return len(self.student)

py_ss = Classes("python全栈9期")

py_ss.student.append("二哥")

py_ss.student.append("泰哥")

print(len(py_ss))

结果呈现

2

## 9 __hash__

class A:

def init(self,name,sex):

self.name = name

self.sex = sex

def hash(self):

return hash(self.name + self.sex)

a = A("agg", "男")

b = A("agg", "男")

print(hash(a)) # 2067652227830744138

print(hash(b)) # 2067652227830744138

c = A("agg", "女")

print(hash(c)) # 2005968340684947333


## 10 __eq__

class A:

def init(self,name):

self.name = name

obj1 = A("egg")

obj2 = A("egg")

print(obj1 == obj2) # False

比较内存地址

class A:

def init(self,name):

self.name = name

def eq(self, other):

if self.name == other.name:

return True

else:

return False

obj1 = A("egg")

obj2 = A("egg")

obj3 = A("egge")

print(obj1 == obj2) # True

print(obj1 == obj3) # False


## 11 例1 纸牌游戏

from collections import namedtuple

Card = namedtuple("Card", ["rank", "suit"]) # rank 牌面大小 suit牌面花色

c1 = Card(2, "红心")

print(c1) # Card(rank=2, suit=‘红心‘)

print(c1.suit) # 红心

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 __str__(self):
    return json.dumps(self._cards,ensure_ascii=False)      # json 序列化

deck = FranchDeck()

print(deck[0]) # 第一张牌

from random import choice

print(choice(deck)) # 随机抽牌

print(choice(deck)) # 随机抽牌

from random import shuffle

shuffle(deck) # 洗牌

print(deck._cards[:5]) # 获取前5 个

print(deck[:5]) # 获取前5 个 item方法

import json

print(deck) # 查看所有牌面


## 12 例2 100个对象 名字和性别和年龄不同

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(10):

p_lst.append(Person(‘egon‘,i,‘male‘))

print(p_lst)

print(set(p_lst))

set 依赖对象的 hash eq

````

  • 转自 :http://www.cnblogs.com/Eva-J/articles/7351812.html

原文地址:https://www.cnblogs.com/xiaoqshuo/p/9778261.html

时间: 2024-10-18 22:51:38

Python - - 面向对象 - - 面向对象进阶的相关文章

Python基础-第七天-面向对象编程进阶和Socket编程简介

本篇内容: 1.面向对象编程进阶-静态方法 2.面向对象编程进阶-类方法 3.面向对象编程进阶-属性方法 4.面向对象编程进阶-特殊成员(内置方法) 5.面向对象编程进阶-反射 6.异常处理.断言 7.Socket编程简介 一.面向对象编程进阶-静态方法 1.静态方法的实现 通过@staticmethod装饰器可以把其装饰的方法变为一个静态方法: 变成静态方法后,形参中可以不用写self了.如果写了self,默认是不会把对象本身传递给self,需要手动传递: class Dog(object):

进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶

Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 要在类中使用静态方法,需在类成员函数前面加上@staticmethod标记符,以表示下面的成员函数是静态函数.使用静态方法的好处是,不需要定义实例即可使用这个方法.另外,多个实例共享此静态方法. 类方法 类方法与普通的成员函数和静态函数有不同之处,在接触的语言中好像也没见过这种语义,看它的定义: 

what' the python之面向对象(进阶)

面向对象的知识点补充(进阶版) classmethod和staticmethod:这两个函数的用途就是可以不用实例化对象就可以调用方法 class Classmethod_Demo(): role = 'dog' @classmethod def func(cls): print(cls.role) Classmethod_Demo.func() class Staticmethod_Demo(): role = 'dog' @staticmethod def func(): print("当普

Python之面向对象进阶

Python之面向对象进阶 进阶有:Python 类的成员.成员修饰符.类的特殊成员. 一.类的成员 类的成员可以分为三大类:字段.方法和属性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份. 1.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 1 class Province:

python面向对象编程进阶

python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 class Foo(object): 2 pass 3 4 obj = Foo() 5 6 isinstance(obj, Foo) issubclass(sub, super)检查sub类是否是 super 类的派生类 1 class Foo(object): 2 pass 3 4 class B

[.net 面向对象程序设计进阶] (2) 正则表达式(一)

[.net 面向对象程序设计进阶] (2) 正则表达式(一) 1.什么是正则表达式? 1.1正则表达式概念 正则表达式,又称正则表示法,英文名:Regular Expression(简写为regex.regexp或RE),是计算机科学的一个重要概念.他是用一种数学算法来解决计算机程序中的文本检索.区配等问题. 1.2正则表达式语言支持  正则表达式其实与语言无关,在很多语言中都提供了支持 ,包括最常用的脚本语言Javascript.当然C#语言也毫不例外的提供了很好的支持.     正则表达式语

My way to Python - Day05 - 面向对象-思维导图

My way to Python - Day05 - 面向对象 思维导图

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习表达式在程序设计中的优点:比如构造动态查询.动态构造表达式树完成未知对象属性访问,比反射的性能高出很多.我们可以说表达式树才是Lambda的精髓,是我们必须要熟练掌握并灵活运用的. 1.关于表达式树(Expression Tree) 表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如

[.net 面向对象程序设计进阶] (14) 缓存(Cache) (一) 认识缓存技术

[.net 面向对象程序设计进阶] (14) 缓存(Cache)(一) 认识缓存技术 本节导读: 缓存(Cache)是一种用空间换时间的技术,在.NET程序设计中合理利用,可以极大的提高程序的运行效率. 本节将介绍如何利用缓存写出高效率的代码. 1. 什么是缓存(Cache)? 缓存(Cache)是一种用空间换取时间的技术 存在于计算机中很多地方,用来将一些慢速设备中的常用数据保存在快速设备中,取数据的时候直接从快速设备中取. 比如CPU二级缓存.内存.windows文件读取缓存. 2. .NE

[.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit

[.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境 http://www.cnblogs.com/yubinfeng/p/5182271.html 本篇导读: 上篇介绍了一款Windows环境下的Git服务器工具GitStack ,搭建了最简单的Windows下的Git服务器,需要再次提醒的是