python学习笔记(十三)面向对象3

面向对象

对象支持函数调用

示例:

def hello():
    print('Hello world!')
    
hello()

a = 250
# callable() 函数用于检查一个对象是否是可调用的
print(callable(a))

class Person:
    # 将对象当做函数调用时会自动触发
    def __call__(self, *args, **kwargs):
        print('__call__')
        print(args)
        print(kwargs)   

p = Person()

p(1, 2, 3, name='dahua', age=18)

# 判断是否可调用
# print(callable(p))

# 判断是否有call属性
print(hasattr(p, '__call__'))

# 判断是否是函数
from inspect import isfunction
print(isfunction(p))

抽象基类(了解)

说明:

抽象基类的作用不是为了创建对象(实例化)的
抽象基类是为了统一接口而存在的
示例:
注意 abc 是一个库 不要再 命名的时候 随意命名成 abc 而出现问题
抽象方法:子类中必须实现,所有可以统一接口

from abc import ABC, abstractmethod

# 抽象基类
class Animal(ABC):
    # 定义抽象方法:子类中必须实现,所有可以统一接口
    @abstractmethod
    def run(self):
        pass
    
# a = Animal()

# 子类必须实现基类中的抽象方法,否则无法实例化
class Dog(Animal):
	def run(self):
      	print('狗喜欢疯跑') 
        
d = Dog()

class Cat(Animal):
 	def run(self):
      	print('猫喜欢走猫步') 

c = Cat()

魔术方法

回顾:

魔术方法 触发时机
__ str __ 打印 或 转换为字符串
__ init __ 构造方法,创建对象后初始化时
__ del __ 析构方法,对象即将销毁时
__ setattr __ 设置属性
__ getattr __ 获取不存在的属性
__ delattr __ 删除属性
__ setitem __ 当做字典操作,设置属性
__ getitem __ 当做字典操作,获取属性
__ delitem __ 当做字典操作,删除属性
__ call __ 将对象当做函数调用时
repr

a = 10
b = 20

# 会执行有效的python代码字符串
c = eval('a + b')

print(c)

d = eval("{'name': 'dahua', 'age': 18}")
print(d, type(d))

# 可以得到对象创建的字符串表示形式
# repr() 函数将对象转化为供解释器读取的形式。
s = repr(d)
print(s, type(s))

# 自定义对象
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
	# 对象使用repr函数处理时会自动触发,打印对象(str不存在)时也会触发        
    # 通常返回对象创建的字符串表示形式
    def __repr__(self):
        return "Person('{}', {})".format(self.name, self.age)

    # 打印对象时:首先找__str__,然后找__repr__,最后打印 类名+地址
    def __str__(self):
        return 'name:{} age:{}'.format(self.name, self.age)  
    
xiaoming = Person('xiaoming', 18)

s = repr(xiaoming)
print(s)

xm2 = eval(s)
print(xm2)

算术运算符重载

class Number:
    def __init__(self, num):
        self.num = num

    # 当对象出现在 '+' 的左边时会自动触发
    def __add__(self, other):
        print('__add__')
        return self.num + other

    # 当对象出现在 '+' 的右边时会自动触发
    def __radd__(self, other):
        print('__radd__')
        return self.num + other

    # '+='运算时会自动触发,若没有实现则会尝试__add__
    def __iadd__(self, other):
        # print('__iadd__')
        self.num += other
        return self

    def __str__(self):
        return 'num:{}'.format(self.num)
    
n = Number(10)

# ret = n + 20
# ret = 20 + n
# print(ret)

n += 20
print(n) 

关系运算符重载

class Number:
    def __init__(self, num):
        self.num = num

    # 大于:>
    def __gt__(self, other):
        print('__gt__')
        return self.num > other
    
    # 大于等于:>=
    def __ge__(self, other):
        print('__ge__')
        return self.num >= other
    
    # 小于:<
    def __lt__(self, other):
        print('__lt__')
        return self.num < other
    
    # 小于等于:<=
    def __le__(self, other):
        print('__le__')
        return self.num <= other

    # 等于:==
    def __eq__(self, other):
        print('__eq__')
        return self.num == other

    # 不等于:!=,当没写时会尝试__eq__
    def __ne__(self, other):
        print('__ne__')
        return self.num != other
    

n = Number(5)

# 大于
# print(n > 4)
# print(4 < n)

# 小于
# print(n < 4)
# print(4 > n)

# print(n == 6)
print(n != 6)

__new__方法

class Person(object):
    # 用于创建对象
    def __new__(cls, *args, **kwargs):
        print('__new__')
        # 创建对象,然后返回
        return object.__new__(cls)

    # 用于初始化对象
    def __init__(self):
        print('__init__')
        

# p = Person.new(Person)
# p.init()
# 相当于执行了上面两句(创建对象+初始化)
# p = Person()
 
p1 = Person()
p2 = Person()

print(id(p1))
print(id(p2))

设计模式

说明:针对特定场景问题的特定解决方案

单例模式:无论创建多少次,得到的对象始终是同一个

示例:

class Person(object):
    def __new__(cls, *args, **kwargs):
        # 判断当前类是否拥有_instance属性
        if not hasattr(cls, '_instance'):
        	# 只有第一次创建才会出现  后面进行创建的话 都是同一个
            print('创建对象')
            cls._instance = object.__new__(cls)
        return cls._instance
 
p1 = Person()
p2 = Person()

print(id(p1))
print(id(p2))

属性函数

说明:将成员方法当做属性一样访问

作用:可以干预指定属性的获取及设置操作

示例:

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password

    # 获取器:获取password属性时自动触发 相当于将passwordb保护起来  返回给用户 我们想让他看见的
    @property
    def password(self):
        print('你想干啥?')
        return '偷看密码,不可能'

    # 设置器:设置password属性时自动触发
    @password.setter
    def password(self, password):
        print('设置密码', password)
        self.__dict__['password'] = 'xxx' + password + 'yyy'
        
        
user = User('xiaoming', '123456')
print(user.password)

# user.password = '654321'
print(user.__dict__)        

内存管理

非常经典

概念:保证不再使用的对象得到合理及时的释放

引用计数:

当创建一个对象赋值给一个变量时,将引用计数记为1;当多一个变量指向该对象,引用计数加1;当少一个变量指向该对象时,引用计数减1,减到0时释放对象,顺便回调用对象的__del__方法释放相关的资源

说明:引用计数是对可变变量及自定义对象而言的,不可变变量对于我们来说没有研究的意义

示例:

a = 10
b = 10

print(id(a))
print(id(b))

from sys import getrefcount

# 不可变变量的引用计数没有意义
print(getrefcount(a))

lt = [1, 2, 3]

lt2 = lt

# 函数本身会增加1次引用计数
print(getrefcount(lt))
del lt2
print(getrefcount(lt))

class Person:
    def __del__(self):
      	print('对象即将释放')
        
p = Person()
print(getrefcount(p))

del p
print('OVER')       

引用传递

def test(n):
    n += 1
    
# 不可变变量传递的是值
num = 10

# test(num)
# test(n=num)
# test(n=10)
test(10)
print(num)

def demo(lt):
	lt[0] = 100
    
# 可变变量传递的引用
l = [1, 2, 3]
demo(lt=l)
print(l)
# 100 2 3

# 默认值是可变变量,永远都是同一个
def fun(lt=[]):
    print(id(lt))
    lt.append('abc')
    return lt

print(fun())
print(fun([]))
print(fun())

生成的是一个算法 每一个列表的元素都是一个函数 但是没有执行
lt = [lambda: x*x for x in range(1, 10)]

print(type(lt[0]))
在这个时候才开始执行
每一个算法中都会进行循环到9
print(lt0)
print(lt1)
print(lt2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值