Penjelasan terperinci tentang penjana, iterator, atribut dan kaedah yang ditambah secara dinamik dalam Python

WBOY
Lepaskan: 2023-04-21 13:22:08
ke hadapan
1363 orang telah melayarinya

1. Penjana

1. Definisi Penjana

Dalam Python, mekanisme yang mengira semasa gelung dipanggil penjana

2 kewujudan peranti

Semua data dalam senarai berada dalam ingatan Jika terdapat sejumlah besar data, ia akan menggunakan banyak memori.

Contohnya: jika anda hanya perlu mengakses beberapa elemen pertama, maka semua ruang berikutnya akan terbuang

Jika elemen senarai dikira mengikut algoritma tertentu, anda boleh mengira secara berterusan elemen seterusnya semasa gelung, jadi anda tidak perlu membuat senarai lengkap, sekali gus menjimatkan banyak ruang.

3. Kaedah 1 mencipta penjana (ungkapan penjana)

Ungkapan penjana adalah sangat mudah. ​​Cuma tukar [] dalam pemahaman senarai kepada () untuk mencipta Penjana:

L = [x * x for x in range(10)]  #推导式
print(L)
g = (x * x for x in range(10)) #加成括号就是生成器
print(g)
#<generator object <genexpr> at 0x1022ef630>
&#39;&#39;&#39;L是一个list,而g则是一个 generator&#39;&#39;&#39;
Salin selepas log masuk

4. Kaedah 2 untuk mencipta penjana (fungsi penjana)

1. Fungsi Penjana
  • Jika sesuatu fungsi mengandungi kata kunci hasil, maka fungsi bukan lagi fungsi biasa. Memanggil fungsi mencipta objek penjana

  • Fungsi penjana: Gunakan hasil kata kunci untuk mengembalikan hasil sekaligus, sekat dan mulakan semula

    < . untuk menjalankan ke pernyataan hasil seterusnya, mendapatkan setiap nilai pulangan satu demi satu sehingga tiada pernyataan hasil, dan akhirnya mencetuskan pengecualian StopIteration
hasil adalah bersamaan dengan pulangan, yang mengembalikan nilai dan mengingati kedudukan yang dikembalikan Semasa lelaran seterusnya, kod mula melaksanakan daripada penyataan seterusnya (bukan baris seterusnya) hasil
  • Hantar(), seperti seterusnya(), boleh buat penjana pergi selangkah lebih jauh (berhenti lain kali ia menemui hasil), tetapi send() boleh lulus nilai, yang digunakan sebagai hasil keseluruhan ungkapan hasil
  • Cara penjana ujian berfungsi (hasil)
Cara penjana ujian berfungsi (hantar)

Ringkasan
&#39;&#39;&#39;
如果一个函数中包含 yield 关键字,那么这个函数就不再是一个普通函数,
调用函数就是创建了一个生成器(generator)对象
生成器函数:其实就是利用关键字 yield 一次性返回一个结果,阻塞,重新开始
原理
1. 函数有了yield之后,调用它,就会生成一个生成器
2. 下次从下一个语句执行,切记不是下一行(tmp = yield i)
3. return在生成器中代表生成器种植,直接报错:StopIeratation
4. next方法作用:唤醒并继续执行
&#39;&#39;&#39;
def test():
    print("start")
    i = 0
    while i<3:
        &#39;&#39;&#39;yield i #第一次执行,此处挂起;同时将i的值返回到i
                   #第二次执行,从挂起的地方往下执行&#39;&#39;&#39;
        temp = yield i #下次迭代时,代码从`yield`的下一条语句(不是下一行)开始执行
        print(f"i:{i}")
        i += 1
    print("end")
    return "done"
if __name__ == &#39;__main__&#39;:
    a = test()
    print(type(a))
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())# 抛出异常:StopIteration
&#39;&#39;&#39;
<class &#39;generator&#39;>
start
0
temp:None
1
temp:None
2
temp:None
end
Traceback (most recent call last):
 in <module>
    print(a.__next__())# 抛出异常:StopIteration
StopIteration: done
&#39;&#39;&#39;
Salin selepas log masuk

1. Apakah itu penjanaPenjana hanya menyimpan satu set algoritma untuk menjana nilai, dan tidak membenarkan algoritma mula dilaksanakan sekarang, tetapi Apabila saya memanggilnya, bilakah ia mula mengira nilai baharu dan mengembalikan anda

&#39;&#39;&#39;
send的作用是唤醒并继续执行,发送一个信息到生成器内部
&#39;&#39;&#39;
def foo():
    print("start")
    i = 0
    while i < 2:
        temp = yield i
        print(f"temp:{temp}")
        i += 1
    print("end")
 
g = foo()
print(next(g))  #等同g.__next__(),next是内置函数
print("*"*20)
print(g.send(100))
print(next(g))
# for a in g:#g所返回的值是yield处的i
#     print(a)
&#39;&#39;&#39;
start
0
********************
temp:100
1
temp:None
end
Traceback (most recent call last):
    print(next(g))
StopIteration
&#39;&#39;&#39;
Salin selepas log masuk
2. Ciri penjana

Fungsi penjana menjana satu siri hasil. Selepas mengembalikan nilai melalui kata kunci hasil, ia boleh terus berjalan dari tempat ia keluar, jadi satu siri nilai boleh dijana pada bila-bila masa.

Penjana dan lelaran berkait rapat dengan kaedah ahli __next__(), yang sama ada mengembalikan item lelaran seterusnya atau menyebabkan pengecualian untuk menamatkan lelaran.
  • Penjana ialah program khas yang boleh digunakan untuk mengawal kelakuan lelaran gelung,
  • 2. Iterator
  • 1. Konsep

Lelaran ialah salah satu fungsi Python yang paling berkuasa dan cara untuk mengakses elemen koleksi

Iterator Ia adalah objek yang boleh mengingati kedudukan yang dilalui
  • Objek iterator mula mengakses dari elemen pertama koleksi sehingga semua elemen telah diakses
  • Iterators hanya boleh pergi ke hadapan dan bukan ke belakang
  • Iterators mempunyai dua kaedah asas:
  • iter()
  • dan

    netx( )

  • 2. Perbezaan antara objek boleh lelar dan lelaran

    Objek yang melaksanakan kaedah iter dipanggil Objek boleh lelar"

Objek yang melaksanakan kaedah seterusnya dan boleh diulang dipanggil "iterator" Iterator Iaitu, objek yang melaksanakan kaedah iter dan kaedah seterusnya ialah iterator
  • <🎜. >

  • !
  • Penjana adalah semua

    Iterator

    objek, tetapi
  • senarai
,
dict

, str semuanya Boleh Diulang (Iterable objek), tetapi bukan Iterator (Iterator)

Python's
Iterator
&#39;&#39;&#39;
生成器一定是迭代器
可迭代对象不一定是迭代器,使用iter([])封装后可转为迭代器
&#39;&#39;&#39;
from collections.abc import Iterator
from collections.abc import Iterable
a = isinstance([], Iterator) #list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器)
print(a)
a = isinstance([], Iterable) #可迭代对象
print(a)
"""
执行结果:
False
True
"""
Salin selepas log masuk
objek Mewakili
&#39;&#39;&#39;list、dict、str 等 Iterable 变成 Iterator,可以使用 iter() 函数:&#39;&#39;&#39;
b = isinstance(iter([]), Iterator)
print(b)
b = isinstance(iter(&#39;花非人陌&#39;), Iterator)
print(b)
 
"""
执行结果:
True
True
"""
Salin selepas log masuk
aliran data

. Data ini boleh dianggap sebagai urutan tersusun, tetapi kami tidak dapat mengetahui panjang jujukan terlebih dahulu Kami hanya boleh mengira data seterusnya atas permintaan melalui fungsi Penjelasan terperinci tentang penjana, iterator, atribut dan kaedah yang ditambah secara dinamik dalam Python next()

, jadi
Iterator <. Pengiraan 🎜> malas, ia hanya akan dikira apabila data seterusnya perlu dikembalikan.

Jadi, penjana mestilah seorang lelaran. 3. Intipati untuk gelung4. Mencipta lelaran

Kelas yang digunakan sebagai lelaran perlu melaksanakan dua kaedah dalam kelas.

__iter__()

dan
__next__()

#Python3 的 for 循环本质就是通过不断调用 next() 函数实现的。
 
for x in [1,2,3,4,5]:
    pass
 
&#39;&#39;&#39;本质是:&#39;&#39;&#39;
#首先获得Iterator对象:
it = iter([1,2,3,4,5])
#循环
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration 就退出循环
        break
Salin selepas log masuk

__iter__() kaedah mengembalikan objek iterator khas, ini The iterator objek melaksanakan kaedah __next__() dan mengenal pasti penyiapan lelaran melalui pengecualian StopIteration

  • __next__() 方法会返回下一个迭代器对象

  • #创建一个依次返回10,20,30,...这样数字的迭代器
    class MyNumbers:
        def __iter__(self):
            self.num = 10
            return self
     
        def __next__(self):
            if self.num < 40:
                x = self.num
                self.num += 10
                return x
            else:
                raise StopIteration
     
    myclass = MyNumbers()
    myiter = iter(myclass)
    print(next(myiter))
    print(next(myiter))
    print(next(myiter))
    print(next(myiter))
    """
    执行结果:
    10
    20
    30
    Traceback (most recent call last):
        raise StopIteration
    StopIteration
    """
    """
    程序解析:
    在这段代码中,MyNumbers 类定义了一个迭代器。该迭代器的作用是生成一系列数字,从 10 开始,每次增加 10,直到 40,然后停止。
    在程序中,通过 iter(myclass) 方法获取 MyNumbers 类的迭代器对象 myiter,然后调用 next(myiter) 方法获取下一个数字。
    在第一次调用 next(myiter) 方法时,迭代器会执行 __next__() 方法,返回 self.num 的值 10,然后将 self.num 的值增加 10,变为 20。
    在第二次、第三次调用 next(myiter) 方法时,迭代器会再次执行 __next__() 方法,返回 20 和 30,然后将 self.num 的值分别增加 10,变为 30 和 40。
    在第四次调用 next(myiter) 方法时,迭代器再次执行 __next__() 方法,发现 self.num 的值已经大于等于 40,于是抛出 StopIteration 异常,表示迭代已经结束。
    """
    Salin selepas log masuk

    三、动态添加属性和方法

    1、动态编程语言定义

    指在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,

    已有的函数可以被删除或是其他结构上的变化

    2、运行过程中给对象添加属性和方法

    #coding=utf-8
    import types
    class Person():
        def __init__(self, name, age):
            self.name = name
            self.age = age
     
    p1 = Person("zhangsan", 20)
    p2 = Person("lisi", 18)
    #动态给对象添加属性和方法
    p1.score = 100
    print(p1.score) #加给p1的只能p1用,对象的也是一样
     
    #动态给对象添加方法
    def run(self):
        print(f"{self.name}, running...")
    p1.run = types.MethodType(run, p1)
    #而types.MethodType(run,p1)则是告诉解释器,self指的就是p1
    p1.run()
    """
    执行结果:
    100
    zhangsan, running...
    """
    Salin selepas log masuk

    3、给类动态添加静态方法以及类方法

    #encoding=utf-8
    class Person():
        __slots__ = {"name", "age"}
        def __init__(self, name, age):
            self.name = name
            self.age = age
     
    @staticmethod
    def staticfunc():
        print("--- static method ---")
     
    Person.staticfunc = staticfunc
    Person.staticfunc()
    Person.score = 1000 #动态给对象静态方法
    print(Person.score)
     
    @classmethod
    def clsfunc(cls):
        print(&#39;--- cls method ---&#39;)
    Person.clsfunc = clsfunc    #动态增加类方法
    Person.clsfunc()
    Salin selepas log masuk

    四、限制动态添加

    1、slots

    1. __slots__的作用
    • __slots__ 对动态添加成员变量、成员方法有限制。对动态添加类属性、类方法没有限制

    • __slots__ 只对本类有限制,不限制子类

    2. 对动态添加成员变量、成员方法有限制
    &#39;&#39;&#39;
    MyClass 类使用 __slots__ 属性限制了实例对象的属性,只允许动态添加 x 属性。
    因此,obj.x = 1 可以成功,但是 obj.y = 2 会抛出 AttributeError 异常
    &#39;&#39;&#39;
    class MyClass:
        __slots__ = [&#39;x&#39;]
     
    obj = MyClass()
    obj.x = 1  # 可以动态添加 x 属性
    obj.y = 2  # 报错,__slots__ 限制了不能动态添加 y 属性
    """
    执行结果:
    AttributeError: &#39;MyClass&#39; object has no attribute &#39;y&#39;
    """
    Salin selepas log masuk
    3. 对动态添加类属性、类方法没有限制
    class MyClass:
        __slots__ = [&#39;x&#39;]
        classattr = 1
     
        @classmethod
        def myclassmethod(cls):
            print("class method")
     
     
    MyClass.newclassattr = 2  # 可以动态添加类属性
    print(MyClass.newclassattr)
    MyClass.mynewclassmethod = lambda cls: print("new class method")  # 可以动态添加类方法
    MyClass.mynewclassmethod(MyClass)   #传递类本身作为参数
    obj = MyClass()
    obj.x  = 3    # 可以动态添加实例属性
    print(obj.x)  # 可以动态添加 x 属性
    """
    执行结果:
    2
    new class method
    3
    """
    Salin selepas log masuk

    Atas ialah kandungan terperinci Penjelasan terperinci tentang penjana, iterator, atribut dan kaedah yang ditambah secara dinamik dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Label berkaitan:
    sumber:yisu.com
    Kenyataan Laman Web ini
    Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
    Tutorial Popular
    Lagi>
    Muat turun terkini
    Lagi>
    kesan web
    Kod sumber laman web
    Bahan laman web
    Templat hujung hadapan