Python进阶知识

news2024/11/27 12:34:50

目录

一、装饰器和闭包

1、装饰器 decorator

2、闭包 closure

二、迭代器与生成器

二、面向对象编程

1、概念

2、类和对象

2.1 概念

2.2 定义类和创建对象

2.3  __init__(self):

2.4 self的理解

3、魔术方法

3.1__str__()

3.2 __new__()

4、析构方法

5、类的继承*

5.1 单继承

5.2 多继承

5.3 重写和调用父类方法

6、多态

7、类方法和静态方法

8、私有化属性和方法--保护和控制数据

8.1私有化属性

 8.2 私有化方法

9、property属性函数

实现方法1-- 类属性

实现方法2:装饰器*

 11、异常处理

 Python内置异常类型:

Exception:万能类型、可以捕获所有异常

自定义异常

12、动态添加属性和方法

12.1 动态添加属性

12.2动态添加方法(需要用到types模块)

12.3 动态绑定类方法和静态方法

13、__slots__属性


一、装饰器和闭包

1、装饰器 decorator

定义:在不修改目标函数代码的前提下,为目标函数添加新功能的函数。

本质上就是一个函数(或类)

作用:为函数增加新功能,减少重复性操作,使代码简洁

使用场景:性能测试、打印日志等

使用装饰器的步骤:

  1. 定义装饰器
  2. 通过@调用装饰器
import time
#定义装饰器
def timer(function):
    def wrapper():
        time_start=time.time()
        function()
        time_end=time.time()
        cost_time=time_end-time_start
        print("花费时间:{}秒".format(cost_time))
    return wrapper

#通过@调用装饰器
@timer
def func1():
    print('我是一个函数1')

@timer
def func2():
    print('我是一个函数2')

func1()
func2()

# 我是一个函数1
# 花费时间:0.0秒
# 我是一个函数2
# 花费时间:0.0秒

2、闭包 closure

定义:在一个内部函数里,对外部作用域(但不是全局作用域)里变量进行引用,这个内部函数就是闭包

def f():
    a=1
    def g():
        nonlocal a#只访问不更改不需要nonlocal,更改需要添加nonlocal
        a += 1
        print(a)
    return g

g1=f()
g2=f()

g1()#2
g1()#3
g1()#4
g2()#2
def f():
    a=[[],[]]
    def g():
        a[0].append(111)
        print(a)
        print(id(a[0]),id(a[1]))

    return g

g1=f()
g2=f()

g1()
g1()
g2()
#[[111], []]
#2043067833216 2043066699392
#[[111, 111], []]
#2043067833216 2043066699392
#[[111], []]
#2043067833664 2043067832704

二、迭代器与生成器

 迭代:一种操作,逐个获取数据的过程称为迭代,如for循环

可迭代对象()、[ ]、{ }、文件对象都是可以迭代的

迭代器 iterator:它包含一组元素,每次调用会返回自身的下一个元素,一个迭代器对象必须是定义了_iter()_方法和next()方法的

  • 所有可迭代对象都可以用 lter() 函数转变为迭代器
  • 迭代器对象可以用next() 不断返回下一个数据,但是当所有元素都被返回时,再执行next(),程序会报错--stoplteration
  • 不能提前知道序列长度,即不能使用len()计算序列长度

生成器 generator :是特殊的迭代器

定义:在Python中,使用了yield的函数 就是生成器

在调用生成器运行的过程中,每次遇到yield时,函数会暂停并保存当前所有运行信息,返回yield值,并在下一次执行next()方法时从当前位置继续运行

#简单的生成器示例:利用生成器输出1-10000000000的数
list=(i for i in range(1,10000000001))
for item in list:
    print(item)

注意:这里是(),而不是[ ],如果使用列表,内存会爆炸

# 生成器
def gen(num):
    while num>0:
        yield num
        num -= 1
    return

g=gen(5)#调用生成器函数,返回一个生成器对象到g里

first=next(g)#使用next函数时才开始真正运行他的函数本体,此时first=5
for i in g: #每次都call了个next
    print(i)
#4
#3
#2
#1

迭代器和生成器的区别

从使用者角度,生成器和迭代器是没什么区别的,使用方法几乎一样

        生成器有send用法,在生成器yield之后,把yield的东西变成一个值,这个值还可以继续赋给生成器函数中的其他变量

#send用法
def gen(num):
    while num>0:
        tmp=yield num #将yield的值赋给tmp
        if tmp is not None:
            num=tmp
        num-=1

g=gen(5)
first=next(g) #first=g.send(None)
print(f"first:{first}")
print(f"send:{g.send(10)}")#10赋值给tmp,num=tmp=10,next()出10

for i in g:
    print(i)

# first:5
# send:9
# 8
# 7
# 6
# 5
# 4
# 3
# 2
# 1

从背后原理,迭代器是将迭代时的状态保存到一个对象里的;生成器是将状态保存到frame,它的状态是函数记录到哪一步,而不是通过一个变量记录状态,更为简洁

生成器的代码量比传统的迭代器少很多

二、面向对象编程

oop三大特征:继承、多态、封装

1、概念

面向过程:一开始学习的,按照解决问题的步骤编程【根据业务逻辑从上到下编程】

函数式:将某功能代码封装到函数中,下次使用直接调用,无需重复编写

面向对象编程:将数据与函数绑在一起封装,这样能够更快速的开发程序,减少重复代码的重写过程 oop(object oriented programming),是一种解决软件复用的设计和编程方法,这种方法将软件系统中相近相似的操作逻辑和操作应用数据、状态,以的形式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用

面向过程适合做小项目,面向对象适合做大项目

2、类和对象

2.1 概念

类:一个模板,模板里包含多个函数,函数中实现一些功能(汽车图纸、车类)

是一组具有相同或相似属性和行为的多个对象的组合

对象:类的实例化,可以执行类中的函数(宝马)

2.2 定义类和创建对象

定义类:类结构=类名(首字母大写)+属性+方法行为

实例方法:在类内部,用def可以定义实例方法,与一般函数不同的是实例方法必须包含参数,默认第一个参数是self(名字标识可以是其他名字,但这个位置必须被占用)

# class 类名:
#     属性
#     方法
class Person:#类名:首字母大写
    #属性
    name='小明'#类属性
    age=20
    #方法(行为) 实例方法
    def eat(parms):
        parms.name='小红'#实例属性
        print('eating')
        pass
    def run(self):
        print('running')
        pass
    pass

创建对象

格式:对象名=类名()

#创建对象[类的实例化]
xm=Person()
#调用函数
xm.eat()
print('{}的年龄是:{}岁'.format(xm.name,xm.age))

属性

  • 类属性:类对象所拥有的属性(定义在类内部,实例方法外)
  • 实例属性:实例对象拥有的属性,只能通过实例对象访问(实例方法内定义的【通过类似于self.变量名】变量)
class Student:
    name='李明'#类属性
    def __init__(self,age):
        self.age=age#实例属性
        pass
    pass

lm=Student(18)
print(Student.name)
print(lm.name)#类属性可以被类对象和实例对象访问
print(lm.age)#实例属性只能通过实例对象访问
print('不能通过类对象访问实例属性')
print(Student.age)

# 李明
# 李明
# 18
# 不能通过类对象访问实例属性
# Traceback (most recent call last):
#   File "E:\资源下载\workspace\shixun\pythonProject2\2.17多态.py", line 47, in <module>
#     print(Student.age)
# AttributeError: type object 'Student' has no attribute 'age'

类属性和实例属性的访问原理:

2.3  __init__(self):

Python自带的内置函数

是一个初始化方法,用来定义实例属性和初始化数据,在创建对象时自动调用

class Person:
    def __init__(self):
        self.name='小倩'
        self.age=20
    def run(self):
        print('running')
        pass
    pass

xq=Person()#创建新对象时,__init__自动调用
print(xq.name)
#小倩

传递参数(后面实例方法都可以直接使用该参数)

class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self,food):
        print(self.name+'喜欢吃'+food)

xm=Person('小明',21)
xm.eat('苹果')

2.4 self的理解

self和对象指向同一内存地址,self是对象的引用,可以理解为对象自己

class Person:
    def eat(self):
        print('self=%s',id(self))
        pass
    pass

xm=Person()
xm.eat()
print('xm=%s',id(xm))
#self=%s 1760559500112
#xm=%s 1760559500112
  • self只有在类中定义实例方法时才有意义,在调用时不必传入相应参数,而是由解释权自动指向
  • self的名称可以更改,只是约定俗成的定义成了self
  • self指的是类实例对象本身

self传参:

class Person:
    def __init__(self,pro):
        self.pro=pro
    def eat(self,name,food,pro):
        print('%s喜欢吃%s,修的专业是%s,%s'%(name,food,self.pro,pro))
        pass
    pass

xm=Person('通信工程')
xm.eat('小明','榴莲','hhh')
# 小明喜欢吃榴莲,修的专业是通信工程,hhh

3、魔术方法

定义:Python中的一些内置好的特定方法,方法名为“__xxx__”,前后有两个下划线

  • 在进行特定操作时,魔术方法会自动调用

常见的魔术方法:

3.1__str__()

定义了__str__方法,在打印对象时,会执行__str__方法(__str__只能return一个字符串)

class Animal:
    def __init__(self,name,colour):
        self.name=name
        self.colour=colour
    def __str__(self):
        return '我的名字是%s,我的颜色是%s'%(self.name,self.colour)

dog=Animal('旺财','白色')
print(dog)
#我的名字是旺财,我的颜色是白色
#改变打印对象的内容

class Animal:
    def __init__(self,name,colour):
        self.name=name
        self.colour=colour

dog=Animal('旺财','白色')
print(dog)
# <__main__.Animal object at 0x000001E49FEF6FD0>
#直接输出对象的地址

3.2 __new__()

调用对象实例的方法,每调用一次生成一个新对象,cls是class的缩写

class Animal(object):
    def __init__(self,name,colour):
        self.name=name
        self.colour=colour
        print('__init__函数执行')
    def __str__(self):
        return '我的名字是%s,我的颜色是%s'%(self.name,self.colour)
    def __new__(cls, *args, **kwargs):
        print('__new__函数执行')
        # return object.__new__(cls)#这里真正创建对象实例

dog=Animal('旺财','白色')
print(dog)
#__new__函数执行
#None
#解释:还没有生成对象实例
class Animal(object):
    def __init__(self,name,colour):
        self.name=name
        self.colour=colour
        print('__init__函数执行')
    def __str__(self):
        return '我的名字是%s,我的颜色是%s'%(self.name,self.colour)
    def __new__(cls, *args, **kwargs):
        print('__new__函数执行')
        return object.__new__(cls)#这里真正创建对象实例
#        return super().__new__(cls)#若没有父类object,用super()创建对象实例

dog=Animal('旺财','白色')
print(dog)
# __new__函数执行
# __init__函数执行
# 我的名字是旺财,我的颜色是白色

#先执行__new__(),创建对象实例后执行__init__
#__new__()创建实例框架,__init__丰满

__new__方法在__init__方法前执行

__new__方法不能调用自己的__new__方法,即:return cls.__new__(cls)

  • 否则会报错:RecursionError:maximum recursion depth exceeded超过最大递归深度

__new__和__init__的区别

  • __new__:类的实例化方法,必须返回该实例,不然对象创建不成功
  • __init__:做对象的初始化工作,也可以认为是实例的构造方法,接受该实例self并对其构造
  • __new__至少一个参数是cls,代表要实例化的类,该参数在实例化时由Python解释器自动提供
  • __new__要早于__init__函数执行

课后问答

4、析构方法

当一个对象被删除或销毁时,Python解释器默认调用__del__()方法,这个方法也称析构方法,也是一种魔术方法

  • 用于对象的释放,对象一旦被释放,不能再使用

程序执行结束自动调用__del__()

class Animal:
    def __init__(self,name):
        self.name=name
        print('__init__执行')
    def __del__(self):
        print('__del__执行')
    pass

cat=Animal('cat')
print('程序等待中。。。')

# __init__执行
# 程序等待中。。。
# __del__执行

对象被删除时,也会自动调用__del__方法

class Animal:
    def __init__(self,name):
        self.name=name
        print('__init__执行')
    def __del__(self):
        print('__del__执行')
    pass

cat=Animal('cat')
del cat#手动去清理对象
print('*'*20)

# __init__执行
# __del__执行
# ********************

5、类的继承*

Python面向对象的三大特征:封装、继承、多态

封装:把内容封装到某个地方,便于后面的使用【其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取封装的内容】

继承:即子可以继承父的内容(属性和行为)

  • 将多个类共有的方法提取到【父类】中,然后通过继承,极大提高了效率,减少代码的重复编写

5.1 单继承

class Animal:
    def eat(self):
        print('eating')

class Cat(Animal):
    pass


cat1=Cat()
cat1.eat()
#eating

5.2 多继承

子类继承多个父类,用逗号分隔  class C(A,B)

问题是:当多个父类中存在相同方法时,应该调用哪一个呢?

class E:
    def eat(self):
        print('E.eat')
class D:
    def eat(self):
        print('D.eat')
class C(E):
    # def eat(self):
    #     print('C.eat')
        pass
class B(D):
    pass
class A(B,C):
    pass

a1=A()
a1.eat()#查找顺序,A中没有,找B,B中没有,找C
print(A.__mro__)
# D.eat
# (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)

__mro__方法:查询执行顺序

继承的传递性:爸爸继承了爷爷,儿子继承爸爸,也继承了爷爷

5.3 重写和调用父类方法

子类中有个跟父类方法名称一样的方法,相当于重写父类方法(方法覆盖)

重写父类方法后,子类调用父类方法时,调用的是子类的方法

class Father:
    def eat(self):
        print('爸爸')
    pass

class Son(Father):
    def eat(self):
        print('儿子')
    pass
son=Son()
son.eat()
print(Son.__mro__)
# 儿子
# (<class '__main__.Son'>, <class '__main__.Father'>, <class 'object'>)

调用父类方法

class Dog:
    def __init__(self,name,color):
        self.name=name
        self.color=color
    def bark(self):
        print('汪汪汪。。')

class Keji(Dog):
    def __init__(self,name,color,age):#重写父类方法
        # Dog.__init__(self,name,color)#调用父类方法1--手动调用
        super().__init__(name,color)#调用父类方法2--自动调用:super()自动查找父类方,进而调用方法
        self.age=age
    def dark(self):
        print('啊啊啊。。')
        super().bark()#调用父类方法
        print('啊啊啊。。')
    def msg(self):
        print('名字:%s,颜色:%s,年龄:%s'%(self.name,self.color,self.age))

keji=Keji('柯基','黄白',2)
keji.dark()
keji.msg()
# 啊啊啊。。
# 汪汪汪。。
# 啊啊啊。。
# 名字:柯基,颜色:黄白,年龄:2

super():假如继承了多个父类,则会按顺序查找

class Animal:
    def bark(self):
        print('动物叫。。')

class Keji(Animal,Dog):
    def __init__(self,name,color,age):#重写父类方法
        # Dog.__init__(self,name,color)#调用父类方法1
        super().__init__(name,color)#调用父类方法2:super()自动查找父类方,进而调用方法
        self.age=age
    def dark(self):
        print('啊啊啊。。')
        super().bark()#调用父类方法
        print('啊啊啊。。')
    def msg(self):
        print('名字:%s,颜色:%s,年龄:%s'%(self.name,self.color,self.age))

keji=Keji('柯基','黄白',2)
keji.dark()
keji.msg()
# 啊啊啊。。
# 动物叫。。
# 啊啊啊。。
# 名字:柯基,颜色:黄白,年龄:2

6、多态

定义:就是多种状态(形态),就是同一种行为,对于不同子类【对象】有不同的行为表现

想实现多态必须满足的两个条件:

  1. 继承:多态必须发生在父态和子态之间
  2. 重写:子类重写父类方法

作用:增加程序的灵活性和扩展性

鸭子类型:在程序设计中,鸭子类型是动态类型的一种风格。“鸭子测试”可以表述为:“当一个鸟走起来像鸭子,叫起来像鸭子,那么这只鸟可以称为鸭子”

class Animal:
    def say(self):
        print("动物叫")
    pass

class Dog(Animal):
    def say(self):
        print('汪汪汪')
    pass
class Cat(Animal):
    def say(self):
        print('喵喵喵')
    pass

# dog=Dog()
# dog.say()
# cat=Cat()
# cat.say()

def common(obj):
    obj.say()
i=[Dog(),Cat()]
for item in i:
    common(item)
# 汪汪汪
# 喵喵喵

7、类方法和静态方法

类方法:类对象所拥有的方法,用装饰器@classmate标识,类方法的第一个参数必须是类对象,一般以cls作为第一个参数。

可以通过类对象、实例对象调用

class Student:
    name='李华'#类属性

    @classmethod
    def get_name(cls):
        return cls.name#访问类属性

    @classmethod
    def change_name(cls,new_name):
        cls.name=new_name#在类方法中修改类属性的值


print(Student.get_name())#类对象引用
lh=Student()
print(lh.get_name())#实例对象引用
# 李华
# 李华
Student.change_name("小花")
print(Student.get_name())#类对象引用
xh=Student()
print(xh.get_name())#实例对象引用
# 小花
# 小花

静态方法:类对象所拥有的方法,需要用@staticmethod来表示静态方法

class Student:
    name='李华'#类属性
    @staticmethod
    def getdate():
        return  Student.name

print(Student.getdate())#类对象引用
lh=Student()
print(lh.getdate())#实例对象引用
# 李华
# 李华

静态方法一般不会通过实例对象访问

为什么使用静态方法?

静态方法主要用来存放逻辑性代码,在静态方法中,不会涉及到类中方法和属性的操作,数据资源能得到有效利用

#引入第三方时间模块
import time
class Timetest:
    @staticmethod
    def showtime():
        return time.strftime("%H:%M:%S",time.localtime())
    pass

print(Timetest.showtime())
# 15:46:56
  • 类方法的第一个参数是类对象cls,进而去引用类对象的属性和方法
  • 实例方法的第一个参数必须是self,通过self去引用类属性或实例属性,若存在相同名称实例属性和类属性,实例属性优先级最高
  • 静态方法不需要定义额外参数,需要引用属性时,可通过类对象或实例对象去引用

8、私有化属性和方法--保护和控制数据

8.1私有化属性

保护属性安全,不得随意修改,将属性定义成私有化属性,添加可调用的方法去访问

使用私有化属性的场景:

  1. 把特定属性隐藏,不想让类的外部直接调用(不能在外部直接访问,在类的内部可以随意访问)
  2. 保护这个属性,不想让该属性的值随意改变(内部可以修改)
  3. 保护属性,不想让派生类【子类】去继承(子类不能继承父类的私有属性)

语法:两个下划线开头,声明属性为私有属性,不能在类的外部被使用或直接访问

class Person:
    def __init__(self):
        self.name='李四'
        self.__age=18#属性私有化(外部不能访问,内部可以访问)
        pass
    def __str__(self):
        return('{}的年龄是{}'.format(self.name,self.__age))

x1=Person()
print(x1)
print(x1.name)
print(x1.__age)#通过类对象在外部访问(私有化后,不能在外部直接访问)

# Traceback (most recent call last):
#   File "E:\资源下载\workspace\shixun\pythonProject2\2.17多态.py", line 125, in <module>
#     print(x1.__age)#通过类对象在外部访问(私有化后,不能在外部直接访问)
# AttributeError: 'Person' object has no attribute '__age'
# 李四的年龄是18
# 李四

 8.2 私有化方法

语法:方法名前加两个下划线

  • 私有化的方法不能被【子类】继承
  • 外部不能直接调用,内部可以调用

__xxx:方法私有化

__xxx__:魔术方法,Python自有,开发者不要创建

xxx_:避免属性名与Python关键字冲突

9、property属性函数

让调用者能直接以访问属性的方式,而且又能控制的方式

实现方法1-- 类属性

class Animal(object):
    def __init__(self):
        self.__age=18#私有化属性
    def dog(self):#访问私有属性
        return self.__age
    def chance(self,age):#修改私有实例属性
        if age<0:
            print('年龄不能小于0')
            pass
        else:
            self.__age=age
    #定义一个类属性,实现直接访问属性的形式去访问私有的属性
    age=property(dog,chance)

a1=Animal()
print(a1.age)#访问私有属性
#18
a1.age=2#修改私有属性
print(a1.age)
#2

实现方法2:装饰器*

即在方法上使用装饰器

class Animal(object):
    def __init__(self):
        self.__age=18#私有化属性

    @property#通过装饰器修饰添加属性标志,提供一个getter方法
    def dog(self):#访问私有属性
        return self.__age

    @dog.setter#提供一个setter方法
    def chance(self,parms):#修改私有实例属性
        if parms<0:
            print('年龄不能小于0')
            pass
        else:
            self.__age=parms
            pass


a1=Animal()
print(a1.dog)#访问私有属性
#18
a1.chance=2#修改私有属性
print(a1.dog)
#2

10、__new__方法(参考3.2)和单例模式

单例模式:一种常用的软件设计模式

目的:确保某个类中只有一个实例存在

实现步骤:利用类属性保存初次创建的实例对象,第二次实例化对象的时候判断类属性是否保存实例对象,如果有就返回类属性保存的,如果没有就调用父类__new__方法创建新的实例对象

class Student(object):
    __instance=None
    def __init__(self,name,age):
        self.name=name
        self.age=age
        pass
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance=super(Student,cls).__new__(cls)#没有保存实例,就保存
            return cls.__instance
        else:
            return  cls.__instance
        pass
    pass

xm=Student('LH',19)
print(id(xm))
xh=Student('XH',20)
print(id(xh))

# 2390515351312
# 2390515351312
#id相同,说明实例化两次对象,都是同一对象

 11、异常处理

语法格式:

try:
    可能出现错误的代码块
except:
    出错后执行的代码块
else:
    没有错误执行的代码块
finally:
    不管有没有出错都要执行的代码块
try:
    x=x/2
    print(x)
except NameError as msg:
    print(msg)

#name 'x' is not defined

 Python内置异常类型:

Exception:万能类型、可以捕获所有异常

自定义异常

  • 要直接或间接继承Error或Exception
  • 用raise关键字抛出异常
class Toolong(Exception):
    def __init__(self,leng):
        self.leng=leng
        pass
    def __str__(self):
        return '你的长度为%s,过长了。。'%self.leng
    pass


def name_test():
    name=input('请输入你的名字:')
    try:
        if len(name)>4:
            raise Toolong(len(name))
        else:
            print(name)
            pass
        pass
    except Toolong as msg:
        print(msg)
    finally:
        print('执行完毕')

name_test()
# 请输入你的名字:chenq
# 你的长度为5,过长了。。
# 执行完毕

12、动态添加属性和方法

动态语言能在运行时改变其结构;Python、php、JavaScript是动态语言,c、c#、Java是静态语言

所有,Python在程序运行过程中添加属性和方法

12.1 动态添加属性

#动态添加属性
class Animal:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def say(self):
        print('%s 年龄:%s'%(self.name,self.age))
    pass

cat=Animal('小猫',2)
cat.say()

cat.color='花色'#给对象动态添加属性
print(cat.color)
Animal.color='白色'#给类动态添加属性
print(Animal.color)

#小猫 年龄:2
#花色
#白色

12.2动态添加方法(需要用到types模块)

语法:

import types#引入代码块
def 方法名(self):
    xxx
    pass

class 类名:
    xxx
pass

实例名=类名()
实例名.引入方法的新名字=types.MethodType(方法名,实例名)#动态添加方法
实例名.引入方法的新名字()#调用新方法
import types#引入types模块
def run(self):
    print("%s 岁的%s在跑。。"%(self.age,self.name))

class Animal:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    pass

cat=Animal('小猫',2)
cat.run=types.MethodType(run,cat)#动态添加方法
cat.run()#调用方法
#2 岁的小猫在跑。。

12.3 动态绑定类方法和静态方法

语法:类名.新名字=类方法名

@classmethod
def classTest(cls):
    print('这是个类方法')
    pass
@staticmethod
def staticTest():
    print("这是个静态方法")
    pass

class Animal():
    pass
#动态给类添加类方法、静态方法
Animal.classnewname=classTest
Animal.staticnewname=staticTest
#调用类方法,静态方法
Animal.classnewname()
Animal.staticnewname()

13、__slots__属性

作用:限制可以添加的实例属性

class Animal(object):
    __slots__ = ('name','age','weight')#限制添加的属性
    def __str__(self):
        return '%s 。。。%s'%(self.name,self.age)
    pass
xh=Animal()
xh.name='小花'
xh.age=20
xh.weight=45
# xh.height  被限制,运行会报错
print(xh)#小花 。。。20

__dict__:所有可用的属性都存储在这,占用内存高;使用__slots__后,实例中不再有__dict__

class Animal(object):
    # __slots__ = ('name','age','weight')#限制添加的属性
    def __str__(self):
        return '%s 。。。%s'%(self.name,self.age)
    pass
xh=Animal()
xh.name='小花'
xh.age=20
xh.weight=45
# xh.height  被限制,运行会报错
print(xh)#小花 。。。20
print(xh.__dict__)#没有设置__slots__时,所有可用的属性存储在这
# 小花 。。。20
# {'name': '小花', 'age': 20, 'weight': 45}

slots的作用:限制实例的属性;节约内存空间

子类继承父类时,若不声明slots,不继承父类的slots;声明slots后,子类限制属性=父类+自身

class Animal(object):
    __slots__ = ('name','age','weight')#限制添加的属性
    def __str__(self):
        return '%s 。。。%s'%(self.name,self.age)
    pass

class Dog(Animal):
    __slots__ = ('color')#未声明时,不继承父类__slots__,声明后,限制属性=父类+自身
    pass
dog=Dog()
dog.color='白色'
print(dog.color)
# 白色

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/364583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在CentOS-7.9配置vsftpd服务

文章目录一 vsftpd简介二 环境准备三 服务部署3.1 安装软件3.2 编写配置文件3.3 用户授权3.4 启动服务3.5 文件传输测试3.5.1 Windows到Linux3.5.2 filezilla3.5.3 从Linux到Linux一 vsftpd简介 FTP是 File Transfer Protocol 文件传输协议的简称。 VSFTP是 Very Security FTP…

【QT】史上最全最详细的QSS样式表用法及用例说明

目录1. Qt样式表语法2. 选择器2.1 可设置样式的部件2.2 选择器类型2.3 子控件2.4 伪状态3. 属性列表4. 冲突解决5. qss示例1. Qt样式表语法 Qt样式表支持各种属性、伪状态和子控件&#xff0c;可以自定义小部件的外观。 selector { attribute: value }selector:选择器&#xf…

Android Gradle 学习笔记(四)构建块基本单元掌握

本篇主要学习 Gradle 构建脚本的三个基本组建成&#xff1a; project 项目task 任务property 属性 我将会重点介绍 Task&#xff0c;因为它是所有基础中的基础&#xff0c; project 的知识更多和实战有关&#xff08;例如模块化&#xff09;&#xff0c;而 property 本身不过…

新手怎么快速学会并上手SQL语言?收藏版

SQL可以说是程序员、数据库管理员DBA、数据分析师等需要做数据处理和分析岗位最常用的程序语言了。 尤其是一些岗位&#xff0c;工作中并非以数据库为核心&#xff0c;只是偶尔用些数据不需要深度学习&#xff0c;不得不自己去做一些取数的事情&#xff0c;只要学会通过SQL取数…

PS_高低频和中性灰——双曲线

高低频 高低频磨皮&#xff1a;把皮肤分成两个图层&#xff0c;一层是纹理层也就是皮肤的毛孔。 一层是皮肤光滑层没有皮肤细节。 高频”图层为细节层&#xff0c;我们用图章工具修高频 “低频”图层为颜色层&#xff0c;我们用混合画笔修低频 原理&#xff1a;修颜色亮度光影…

用户投稿——详解我了解的 TDengine 以及它所在的时序数据库“战场”

作者&#xff1a;大数据模型本篇文章出自 2022 年“用 TDengine&#xff0c;写 TDengine”征文投稿活动。因为工作的关系&#xff0c;最近几年我接触到过各种国产数据库&#xff0c;唯独对 TDengine 念念不忘。在众多数据库中&#xff0c;TiDB 一枝独秀&#xff0c;OceanBase 出…

渗透中超全的Google hack语法

inurl:Login 将返回url中含有Login的网页intitle:后台登录管理员 将返回含有管理员后台的网页intext:后台登录 将返回含有后台的网页inurl:/admin/login.php 将返回含有admin后台的网页inurl:/phpmyadmin/index.php 将返回含有phpmyadmin后台的网页site:http://baidu.com inur:…

OpenStack手动分布式部署Keystone【Queens版】

目录 Keystone简介 1、登录数据库配置&#xff08;在controller执行&#xff09; 1.1登录数据库 1.2数据库里创建keystone 1.3授权对keystone数据库的正确访问 1.4退出数据库 2、数据库导入Keystone表&#xff08;在controller执行&#xff09; 2.1安装httpd mod_wsgi 2.2备…

nn.Conv2d与nn.Conv3d介绍

nn.Conv2d 1&#xff09;输入的维度为&#xff1a; 2&#xff09;输出的维度为&#xff1a; 其中&#xff0c;Cout是由参数out_channels&#xff08;(int) – 卷积产生的通道数&#xff09;决定。 Hout和Wout计算如下&#xff1a; 3&#xff09;在池化层的计算&#xff1a; …

Windows服务器使用cwRsync实现同步

软件分为客户端和服务器端 实现目的&#xff1a;将服务端C:\tongbu目录中的文件定时同步到客户端C:\target目录中去。 cwRsyncServer&#xff08;服务端&#xff09;配置步骤 1.双击运行wRsyncServer_4.1.0_Installer.exe。 2.这里创建的账户是操作系统的&#xff0c;创建的…

canvas初体验

canvas介绍 Canvas 最初由Apple于2004 年引入&#xff0c;用于Mac OS X WebKit组件&#xff0c;为仪表板小部件和Safari浏览器等应用程序提供支持。后来&#xff0c;它被Gecko内核的浏览器&#xff08;尤其是Mozilla Firefox&#xff09;&#xff0c;Opera和Chrome实现&#x…

webpack实现静态资源缓存

一、配置缓存 我们使用 webpack 来打包我们的模块化后的应用程序&#xff0c;webpack 会生成一个可部署的/dist目录&#xff0c;然后把打包后的内容放置在此目录中。只要/dist目录中的内容部署到 server 上&#xff0c;client&#xff08;通常是浏览器&#xff09;就能够访问此…

OKR之剑·总结篇01:如何开好一场OKR复盘会

作者&#xff1a;vivo 互联网平台产品研发团队 本文是《OKR 之剑》系列之总结第 1 篇—— OKR复盘是OKR生命周期中的重要环节&#xff0c;起着承上启下的重要作用。本篇将和你一起探讨什么是OKR复盘、为什么要进行OKR复盘&#xff0c;接着向你展示团队在OKR复盘方面的实践和改…

【MyBatis】代理开发核心配置文件介绍(二)

&#x1f697;MyBatis学习第二站站~ &#x1f6a9;起始站&#xff1a;MyBatis概述&环境搭建(一) &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 &#x1f44d;希望您能有所收获 一.Mapper代理开发 (1) 引入 在上一篇中我们有提到一点&#xff0c;MyBatis可以…

Linux原来是这么管理内存的(最透彻的一篇)

Linux 内存管理模型非常直接明了&#xff0c;因为 Linux 的这种机制使其具有可移植性并且能够在内存管理单元相差不大的机器下实现 Linux&#xff0c;下面我们就来认识一下 Linux 内存管理是如何实现的。 基本概念 每个 Linux 进程都会有地址空间&#xff0c;这些地址空间由三…

堆的概念和结构以及堆排序

前言 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事&#xff0c…

Sofa-jraft的Rpc调用服务端分析

在sofa-jraft中&#xff0c;关于RPC的服务端是RpcServer在RpcServer中的init方法中&#xff1a;初始化了连接事件监听器&#xff0c;这个里面就是一个map&#xff0c;然后可以添加事件监听的处理器&#xff0c;初始化userProcessors, codec 是一个编码和解码器的工厂&#xff0…

VPS使用ProxySU搭建节点服务器

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰&#xff0c;更不会影响计算机信息系统的正常运行。不得将代码用于非法用途&#xff0c;如侵立删&#xff01; VPS使用ProxySU搭建节点服务器 环境 contos8win10 64位ProxySU 4.1.7 服…

02-mysql高级-

文章目录mysql高级1&#xff0c;约束1.1 概念1.2 分类1.3 非空约束1.4 唯一约束1.5 主键约束1.6 默认约束1.7 约束练习1.8 外键约束1.8.1 概述1.8.2 语法1.8.3 练习2&#xff0c;数据库设计2.1 数据库设计简介2.2 表关系(一对多)mysql高级 今日目标 掌握约束的使用 掌握表关系…

自动化测试——css元素定位

文章目录一、css定位场景二、css相对定位的优点三、css的调试方法1、表达式中含有字符串&#xff1a;表达式中的引号一定和外面字符串的引号相反四、css基础语法1、标签定位2、class定位特别注意&#xff1a;当class类型的属性值包含多个分割值&#xff0c;$(.s_tab s_tab_1z9n…