একটি বেসিক পাইথন ইটারেটর তৈরি করুন


568

কীভাবে একজন পাইথনে একটি পুনরাবৃত্তি ফাংশন (বা পুনরুদ্ধারকারী বস্তু) তৈরি করতে পারে?

উত্তর:


649

পাইথনে আইট্রেটার অবজেক্টগুলি পুনরায় প্রোটোকলের সাথে সামঞ্জস্য করে, যার মূলত তারা দুটি পদ্ধতি সরবরাহ করে: __iter__() এবং __next__()

  • __iter__পুনরুক্তিকারীর বস্তুর ফেরৎ এবং পরোক্ষভাবে লুপ শুরুতে বলা হয়।

  • __next__()পদ্ধতি পরবর্তী মান এবং পরোক্ষভাবে প্রতিটি লুপ বৃদ্ধি এ বলা হয়। প্রত্যাবর্তনের আর কোনও মান না থাকাকালীন এই পদ্ধতিটি স্টিপটিরেটনের ব্যতিক্রম উত্থাপন করে, যা পুনরাবৃত্তি বন্ধ করতে লুপিং কনস্ট্রাক্টস দ্বারা স্পষ্টত ক্যাপচার করা হয়।

এখানে একটি কাউন্টার একটি সাধারণ উদাহরণ:

class Counter:
    def __init__(self, low, high):
        self.current = low - 1
        self.high = high

    def __iter__(self):
        return self

    def __next__(self): # Python 2: def next(self)
        self.current += 1
        if self.current < self.high:
            return self.current
        raise StopIteration


for c in Counter(3, 9):
    print(c)

এটি মুদ্রণ করবে:

3
4
5
6
7
8

পূর্ববর্তী উত্তরে যেমন জেনারেটর ব্যবহার করে এটি লেখা সহজ:

def counter(low, high):
    current = low
    while current < high:
        yield current
        current += 1

for c in counter(3, 9):
    print(c)

মুদ্রিত আউটপুট একই হবে। ফণা অধীনে, জেনারেটর অবজেক্ট পুনরায় প্রোটোকল সমর্থন করে এবং ক্লাস কাউন্টার হিসাবে প্রায় অনুরূপ কিছু করে।

ডেভিড Mertz এর নিবন্ধ, Iteilers এবং সাধারণ জেনারেটর , একটি বেশ ভাল ভূমিকা।


4
এটি বেশিরভাগই একটি ভাল উত্তর, তবে এটি স্ব-স্ব ফিরে আসার বিষয়টি একটু উপ-অনুকূল is উদাহরণস্বরূপ, আপনি যদি লুপের জন্য দ্বিগুণ নেস্টে একই কাউন্টার অবজেক্টটি ব্যবহার করেন তবে আপনি সম্ভবত যে আচরণটি বোঝাতে চাইছেন তা পাবেন না।
কেসি রডর্মার

22
না, পুনরাবৃত্তিকারীরা তাদের ফিরে আসতে হবে। Iteabless পুনরাবৃত্তি পুনরাবৃত্তি, কিন্তু পুনরুক্তি প্রয়োগ করা উচিত নয় __next__counterএটি একটি পুনরাবৃত্তিকারী, তবে এটি কোনও ক্রম নয়। এটি এর মান সংরক্ষণ করে না। উদাহরণস্বরূপ, লুপের জন্য দ্বিগুণ নেস্টের জন্য কাউন্টারটি ব্যবহার করা উচিত নয়।
লিজ

4
কাউন্টার উদাহরণে, সেলফ কন্টেন্টকে অন্তর্ভুক্ত করা উচিত __iter__(পাশাপাশি __init__)। অন্যথায়, অবজেক্টটি কেবল একবারে পুনরাবৃত্তি হতে পারে। উদাহরণস্বরূপ, যদি আপনি বলেন ctr = Counters(3, 8), তবে আপনি for c in ctrএকাধিকবার ব্যবহার করতে পারবেন না ।
কর্ট

7
@ কার্ট: একেবারে না। Counterএকটি পুনরাবৃত্তকারী এবং পুনরাবৃত্তিকে কেবল একবার পুনরাবৃত্তি করার কথা। আপনি যদি পুনরায় সেট self.currentকরেন __iter__, তবে এর উপরে নেস্ট করা লুপটি Counterসম্পূর্ণরূপে ভেঙে যাবে এবং পুনরাবৃত্তকারীগুলির সমস্ত ধরণের আচরণ (যা iterতাদের প্রতি আহ্বান করা আদর্শবাদী) লঙ্ঘন করা হয়েছে। আপনি যদি ctrএকাধিকবার পুনরাবৃত্তি করতে সক্ষম হতে চান তবে এটি একটি পুনরাবৃত্ত-পুনরুক্তিযোগ্য হওয়া দরকার, যেখানে এটি প্রতিবারই অনুরোধ __iter__করা হয় এবং একেবারে একটি নতুন পুনরাবৃত্তি ফিরিয়ে দেয় । মেশানো এবং মিলানোর চেষ্টা করা (একটি পুনরাবৃত্তকারী যা প্রেরণ করা হওয়ার পরে স্পষ্টত পুনরায় সেট __iter__করা হয়) প্রোটোকল লঙ্ঘন করে।
শ্যাডোর্যাঞ্জার

2
উদাহরণস্বরূপ, যদি Counterকোনও অ-পুনরাবৃত্তির পুনরাবৃত্তিযোগ্য হতে হয়, আপনি __next__/ nextসম্পূর্ণরূপে সংজ্ঞাটি মুছে ফেলতে এবং সম্ভবত __iter__এই উত্তরটির শেষে বর্ণিত জেনারেটরের মতো একই ফর্মের জেনারেটর ফাংশন হিসাবে পুনরায় সংজ্ঞায়িত করতে পারেন (সীমার পরিবর্তে ব্যতীত আর্গুমেন্ট থেকে আগত __iter__, তারা আর্গুমেন্ট করে দেখতে আগ্রহী হবেন __init__সংরক্ষিত selfএবং থেকে অ্যাক্সেস selfমধ্যে __iter__)।
শ্যাডোর্যাঞ্জার

427

একটি পুনরাবৃত্তি ফাংশন তৈরির চারটি উপায় রয়েছে:

  • একটি জেনারেটর তৈরি করুন ( ফলন কীওয়ার্ড ব্যবহার করে )
  • একটি জেনারেটর এক্সপ্রেশন ( জেন এক্সপ ) ব্যবহার করুন
  • কোনো ইটারেটরে তৈরি করুন (সংজ্ঞায়িত __iter__এবং__next__ (অথবা nextপাইথন 2.x এ))
  • পাইথন নিজেই পুনরাবৃত্তি করতে পারে এমন একটি শ্রেণী তৈরি করুন ( সংজ্ঞায়িত__getitem__ )

উদাহরণ:

# generator
def uc_gen(text):
    for char in text.upper():
        yield char

# generator expression
def uc_genexp(text):
    return (char for char in text.upper())

# iterator protocol
class uc_iter():
    def __init__(self, text):
        self.text = text.upper()
        self.index = 0
    def __iter__(self):
        return self
    def __next__(self):
        try:
            result = self.text[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1
        return result

# getitem method
class uc_getitem():
    def __init__(self, text):
        self.text = text.upper()
    def __getitem__(self, index):
        return self.text[index]

চারটি পদ্ধতি কার্যকর করার জন্য:

for iterator in uc_gen, uc_genexp, uc_iter, uc_getitem:
    for ch in iterator('abcde'):
        print(ch, end=' ')
    print()

যার ফলাফল:

A B C D E
A B C D E
A B C D E
A B C D E

দ্রষ্টব্য :

দুটি জেনারেটর ধরণের ( uc_genএবং uc_genexp) হতে পারে না reversed(); প্লেইন ইটারেটর ( uc_iter) এর জন্য __reversed__ম্যাজিক পদ্ধতিটি প্রয়োজন (যা ডক্স অনুসারে একটি নতুন পুনরাবৃত্তকারীকে ফিরিয়ে দিতে হবে, তবে selfকাজগুলি (অন্তত সিপিথনে)) ফেরত যেতে হবে ; এবং গেটাইটেম পুনরাবৃত্তিযোগ্য ( uc_getitem) এর অবশ্যই __len__ম্যাজিক পদ্ধতি থাকতে হবে:

    # for uc_iter we add __reversed__ and update __next__
    def __reversed__(self):
        self.index = -1
        return self
    def __next__(self):
        try:
            result = self.text[self.index]
        except IndexError:
            raise StopIteration
        self.index += -1 if self.index < 0 else +1
        return result

    # for uc_getitem
    def __len__(self)
        return len(self.text)

অসীম অলসভাবে মূল্যায়নকৃত পুনরুত্থক সম্পর্কে কর্নেল প্যানিকের গৌণ প্রশ্নের উত্তর দেওয়ার জন্য, উপরোক্ত চারটি পদ্ধতির প্রত্যেকটি ব্যবহার করে এখানে উদাহরণগুলি দেওয়া হল:

# generator
def even_gen():
    result = 0
    while True:
        yield result
        result += 2


# generator expression
def even_genexp():
    return (num for num in even_gen())  # or even_iter or even_getitem
                                        # not much value under these circumstances

# iterator protocol
class even_iter():
    def __init__(self):
        self.value = 0
    def __iter__(self):
        return self
    def __next__(self):
        next_value = self.value
        self.value += 2
        return next_value

# getitem method
class even_getitem():
    def __getitem__(self, index):
        return index * 2

import random
for iterator in even_gen, even_genexp, even_iter, even_getitem:
    limit = random.randint(15, 30)
    count = 0
    for even in iterator():
        print even,
        count += 1
        if count >= limit:
            break
    print

যার ফলাফল (কমপক্ষে আমার নমুনা চালানোর জন্য):

0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32

কোনটি ব্যবহার করবেন তা কীভাবে চয়ন করবেন? এটি বেশিরভাগ স্বাদের বিষয়। আমি যে দুটি পদ্ধতিটি প্রায়শই দেখতে পাই তা হ'ল জেনারেটর এবং পুনরায় প্রোটোকল, সেইসাথে একটি সংকর ( __iter__একটি জেনারেটর ফিরিয়ে দেওয়া)।

জেনারেটর এক্সপ্রেশন তালিকা অনুধাবন প্রতিস্থাপনের জন্য দরকারী (তারা অলস এবং তাই সংস্থানগুলিতে সঞ্চয় করতে পারে)।

যদি কারও পূর্ববর্তী পাইথন ২.x সংস্করণ ব্যবহারের সাথে সামঞ্জস্যতার প্রয়োজন হয় __getitem__


4
আমি এই সারাংশটি পছন্দ করি কারণ এটি সম্পূর্ণ। এই তিনটি উপায়ে (ফলন, জেনারেটর এক্সপ্রেশন এবং আয়রেটর) মূলত একই, যদিও কিছু অন্যের চেয়ে সুবিধাজনক। ফলন অপারেটর "ধারাবাহিকতা" ক্যাপচার করে যা এতে রাজ্য থাকে (উদাহরণস্বরূপ আমরা যে সূচকটি আপ করি)। ধারাবাহিকতার "ক্লোজার" এ তথ্য সংরক্ষণ করা হয়। পুনরুক্তি পদ্ধতি পুনরুক্তরের ক্ষেত্রগুলির মধ্যে একই তথ্য সংরক্ষণ করে, যা মূলত বন্ধ হিসাবে একই জিনিস। Getitem পদ্ধতি একটু ভিন্ন, কারণ এটি বিষয়বস্তু মধ্যে সূচী এবং পুনরাবৃত্ত প্রকৃতিতে নয়।
আয়ান

2
@ মেটালপেল: আসলে, তা। উপরের চারটি ক্ষেত্রেই আপনি পুনরাবৃত্তি করতে একই কোডটি ব্যবহার করতে পারেন।
ইথান ফুরম্যান

1
@ আস্টারস্ক: না, uc_iterএর কাজটি শেষ হওয়ার আগে একটি উদাহরণ শেষ হতে হবে (অন্যথায় এটি অসীম দ্বারা হবে); আপনি যদি আবার এটি করতে চান তবে আপনাকে আবার কল করে একটি নতুন uc_iter()পুনরাবৃত্তি পেতে হবে।
এথান ফুরম্যান

2
আপনি সেট করতে পারেন self.index = 0মধ্যে __iter__যাতে তোমাদের উপর অনেক বার পুনরুক্তি করতে পারেন। অন্যথায় আপনি পারবেন না।
জন স্ট্রুড

1
আপনি যদি সময় ব্যয় করতে পারতেন তবে কেন আপনি অন্যের চেয়ে কোনও পদ্ধতি বেছে নেবেন সে সম্পর্কে আমি একটি ব্যাখ্যাটির প্রশংসা করব।
আআআআআআআআআআআআআআআআআআআআআআ

103

প্রথমে ইটারটুলস মডিউলটি সমস্ত ধরণের ক্ষেত্রে অবিশ্বাস্যরূপে কার্যকর যার ক্ষেত্রে একটি পুনরুক্তিকারী কার্যকর হবে তবে অজগরটিতে একটি পুনরুক্তি তৈরি করার জন্য আপনার এখানে প্রয়োজনীয় সমস্ত বিষয়:

উত্পাদ

এটা কি দুর্দান্ত না? ফলন কোনও ফাংশনে স্বাভাবিক রিটার্ন প্রতিস্থাপন করতে ব্যবহার করা যেতে পারে । এটি অবজেক্টটিকে ঠিক একইরূপে ফেরত দেয়, তবে রাষ্ট্রটিকে ধ্বংস করে এবং প্রস্থান করার পরিবর্তে, আপনি যখন পরবর্তী পুনরাবৃত্তি সম্পাদন করতে চান তখন এটি রাষ্ট্র সংরক্ষণ করে। ক্রিয়াকলাপের এটির উদাহরণ উদাহরণ থেকে এটির তাত্ত্বিক ক্রিয়া তালিকা থেকে সরাসরি টানা :

def count(n=0):
    while True:
        yield n
        n += 1

যেমন ফাংশন বর্ণনায় বর্ণিত হয়েছে (এটি গণনা () এটির টোলস মডিউল থেকে ফাংশন ...), এটি একটি পুনরুক্তি তৈরি করে যা এন থেকে শুরু করে পরপর পূর্ণসংখ্যার ফেরত দেয়।

জেনারেটর এক্সপ্রেশনগুলি হ'ল পোকার সম্পূর্ণ ক্যান (দুর্দান্ত কীট!)) এগুলি মেমরি সংরক্ষণের জন্য তালিকার সংকলনের জায়গায় ব্যবহার করা যেতে পারে (তালিকার বোধগম্যতা স্মৃতিতে একটি তালিকা তৈরি করে যা ভেরিয়েবলের জন্য বরাদ্দ না থাকলে ব্যবহারের পরে নষ্ট হয়ে যায়, তবে জেনারেটর এক্সপ্রেশন জেনারেটর অবজেক্ট তৈরি করতে পারে ... যা অভিনব উপায় বলছি Iterator)। এখানে একটি জেনারেটর এক্সপ্রেশন সংজ্ঞা একটি উদাহরণ:

gen = (n for n in xrange(0,11))

এটি সম্পূর্ণ পরিসীমা 0 এবং 10 এর মধ্যে হওয়ার পূর্বনির্ধারিত ব্যতীত উপরের আমাদের পুনরাবৃত্ত সংজ্ঞাটির সাথে খুব অনুরূপ।

আমি সবেমাত্র xrange () (অবাক হয়েছি যা আমি এর আগে দেখিনি ...) এবং এটি উপরের উদাহরণে যুক্ত করেছি। এক্সরেঞ্জ () হ'ল পরিসীমা () এর পুনরাবৃত্তিযোগ্য সংস্করণ যা তালিকার পূর্বনির্মাণ না করার সুবিধা রয়েছে। এটি যদি আপনার পুনরাবৃত্তি করার জন্য ডেটাগুলির একটি দৈত্য কর্পস থাকে এবং কেবল এটির করতে এত মেমরি থাকে তবে এটি খুব কার্যকর হবে।


20
অজগর 3.0 হিসাবে আর কোনও এক্সরেঞ্জ () নেই এবং নতুন পরিসীমা () পুরানো এক্সরেঞ্জের মতো আচরণ করে)

6
আপনার এখনও ২__ তে এক্সরেঞ্জ ব্যবহার করা উচিত, কারণ 2to3 এটিকে স্বয়ংক্রিয়ভাবে অনুবাদ করে।
ফোব

100

আমি আপনার return selfমধ্যে কিছু করতে দেখছি __iter__। আমি কেবল খেয়াল করতে চেয়েছিলাম যে __iter__নিজে নিজেই একটি জেনারেটর হতে পারে (এইভাবে প্রয়োজনীয়তা অপসারণ __next__এবং StopIterationব্যতিক্রম উত্থাপন )

class range:
  def __init__(self,a,b):
    self.a = a
    self.b = b
  def __iter__(self):
    i = self.a
    while i < self.b:
      yield i
      i+=1

অবশ্যই এখানে কেউ সরাসরি জেনারেটর তৈরি করতে পারে তবে আরও জটিল ক্লাসগুলির জন্য এটি কার্যকর হতে পারে।


5
গ্রেট! এটি তাই শুধু লেখা বিরক্তিকর return selfমধ্যে __iter__। আমি যখন yieldএটি ব্যবহার করার চেষ্টা করতে যাচ্ছিলাম তখন আমি খুঁজে পেলাম যে আপনার কোডটি আমি যা চেষ্টা করতে চাই ঠিক তাই করছি।
রায়

3
তবে এক্ষেত্রে কেউ কীভাবে বাস্তবায়ন করবে next()? return iter(self).next()?
লেনা

4
@ লেন্না, এটি ইতিমধ্যে "প্রয়োগ করা হয়েছে" কারণ ইটার (স্ব) একটি পুনরাবৃত্তিকে ফেরত পাঠায়, পরিসরের উদাহরণ নয়।
ম্যানাক্স

3
এটি এটি করার সবচেয়ে সহজ উপায় এবং এটিতে উদাহরণস্বরূপ self.currentবা অন্য কোনও কাউন্টারকে রাখার সাথে জড়িত নয় । এটি শীর্ষ ভোটের উত্তর হওয়া উচিত!
অ্যাস্ট্রোফ্রোগ

4
স্পষ্টতই, এই পদ্ধতিটি আপনার শ্রেণিকে পুনরাবৃত্ত করে তোলে , তবে কোনও পুনরুক্তিকারী নয় । আপনি ক্লাসের উদাহরণগুলিতে প্রতিবার কল করলে আপনি তাজা পুনরাবৃত্তি পান iterতবে সেগুলি নিজেরাই শ্রেণীর উদাহরণ নয়।
শ্যাডোর্যাঞ্জার

13

এই প্রশ্নটি পুনরাবৃত্তিযোগ্য অবজেক্ট সম্পর্কে, পুনরাবৃত্তকারীদের সম্পর্কে নয়। পাইথনে, সিকোয়েন্সগুলি পুনরাবৃত্ত হয় তাই পুনরাবৃত্ত শ্রেণীর তৈরি করার একটি উপায় হ'ল এটি একটি সিক্যুয়েন্সের মতো আচরণ করা, অর্থাৎ এটি __getitem__এবং __len__পদ্ধতিগুলি দেওয়া। আমি পাইথন 2 এবং 3 এ পরীক্ষা করেছি।

class CustomRange:

    def __init__(self, low, high):
        self.low = low
        self.high = high

    def __getitem__(self, item):
        if item >= len(self):
            raise IndexError("CustomRange index out of range")
        return self.low + item

    def __len__(self):
        return self.high - self.low


cr = CustomRange(0, 10)
for i in cr:
    print(i)

1
এটির কোনও __len__()পদ্ধতি থাকতে হবে না । __getitem__একা প্রত্যাশিত আচরণই যথেষ্ট।
ব্ল্যাকজ্যাক

5

একটি জটিল অবজেক্টের জন্য এই পৃষ্ঠার সমস্ত উত্তর সত্যিই দুর্দান্ত। তবে বিল্টিন পুনরাবৃত্ত প্রকারযুক্ত বৈশিষ্ট্যগুলির মতো str, যেমন list, setবা dict, বা কোনও বাস্তবায়ন হিসাবে collections.Iterableআপনি নিজের শ্রেণীর কিছু জিনিস বাদ দিতে পারেন।

class Test(object):
    def __init__(self, string):
        self.string = string

    def __iter__(self):
        # since your string is already iterable
        return (ch for ch in self.string)
        # or simply
        return self.string.__iter__()
        # also
        return iter(self.string)

এটি এর মতো ব্যবহার করা যেতে পারে:

for x in Test("abcde"):
    print(x)

# prints
# a
# b
# c
# d
# e

1
হিসাবে আপনি বললেন, স্ট্রিং ইতিমধ্যে iterable তাই কেন শুধু পুনরুক্তিকারীর জন্য স্ট্রিং (যা জেনারেটর অভিব্যক্তি অভ্যন্তরীণভাবে করে) জিজ্ঞাসা পরিবর্তে মধ্যবর্তী অতিরিক্ত জেনারেটর অভিব্যক্তি: return iter(self.string)
ব্ল্যাকজ্যাক

@ ব্ল্যাকজ্যাক আপনি সত্যই ঠিক বলেছেন কীভাবে আমাকে সেভাবে লিখতে প্ররোচিত করেছিল তা আমি জানি না। সম্ভবত আমি আরও উত্তরাংশের সিনট্যাক্সের ক্ষেত্রে পুনরুক্তি সিনট্যাক্সের কাজটি ব্যাখ্যা করার জন্য একটি উত্তরে কোনও বিভ্রান্তি এড়াতে চাইছিলাম।
জন স্ট্রুড

3

এটি ছাড়া একটি পুনরাবৃত্তিযোগ্য ফাংশন yield। এটি iterফাংশনটি এবং একটি বন্ধ ব্যবহার করে যা listঅজগর 2 এর সংলগ্ন ক্ষেত্রটিতে একটি পরিবর্তনীয় ( ) এ অবস্থায় রাখে ।

def count(low, high):
    counter = [0]
    def tmp():
        val = low + counter[0]
        if val < high:
            counter[0] += 1
            return val
        return None
    return iter(tmp, None)

পাইথন 3 এর জন্য, ক্লোজার স্টেটটি বদ্ধ পরিসরে একটি অপরিবর্তনীয় স্থানে রাখা হয় এবং nonlocalরাষ্ট্রের পরিবর্তনশীল আপডেট করতে স্থানীয় স্কোপে ব্যবহৃত হয়।

def count(low, high):
    counter = 0
    def tmp():
        nonlocal counter
        val = low + counter
        if val < high:
            counter += 1
            return val
        return None
    return iter(tmp, None)  

পরীক্ষা;

for i in count(1,10):
    print(i)
1
2
3
4
5
6
7
8
9

আমি সর্বদা দ্বি-আরগের একটি চতুর ব্যবহারের প্রশংসা করি iter, তবে কেবল স্পষ্ট করে বলার জন্য: এটি কেবলমাত্র yieldভিত্তিক জেনারেটর ফাংশনটি ব্যবহার করার চেয়ে জটিল এবং কম দক্ষ ; পাইথনের yieldভিত্তিক জেনারেটর ফাংশনগুলির জন্য একটি টন দোভাষী সহায়তা রয়েছে যা আপনি এখানে কোড নিতে পারেন না, এই কোডটি উল্লেখযোগ্যভাবে ধীর করে তোলে। তবুও আপ-ভোট দিয়েছেন।
শ্যাডোর্যাঞ্জার

2

আপনি যদি সংক্ষিপ্ত এবং সাধারণ কিছু সন্ধান করেন তবে এটি আপনার পক্ষে যথেষ্ট হবে:

class A(object):
    def __init__(self, l):
        self.data = l

    def __iter__(self):
        return iter(self.data)

ব্যবহারের উদাহরণ:

In [3]: a = A([2,3,4])

In [4]: [i for i in a]
Out[4]: [2, 3, 4]

-1

এখানে ম্যাট গ্রেগরির উত্তর দ্বারা অনুপ্রাণিত হলেন আরও জটিল জটিল পুনরাবৃত্তি যা একটি, বি, ..., জেড, আ, আব, ..., জেডজেড, আ, আব, ..., জাজি, জেডজ

    class AlphaCounter:
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def __next__(self): # Python 3: def __next__(self)
        alpha = ' abcdefghijklmnopqrstuvwxyz'
        n_current = sum([(alpha.find(self.current[x])* 26**(len(self.current)-x-1)) for x in range(len(self.current))])
        n_high = sum([(alpha.find(self.high[x])* 26**(len(self.high)-x-1)) for x in range(len(self.high))])
        if n_current > n_high:
            raise StopIteration
        else:
            increment = True
            ret = ''
            for x in self.current[::-1]:
                if 'z' == x:
                    if increment:
                        ret += 'a'
                    else:
                        ret += 'z'
                else:
                    if increment:
                        ret += alpha[alpha.find(x)+1]
                        increment = False
                    else:
                        ret += x
            if increment:
                ret += 'a'
            tmp = self.current
            self.current = ret[::-1]
            return tmp

for c in AlphaCounter('a', 'zzz'):
    print(c)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.