Package: kothon
KothonKothon is a Python library designed to bring the elegance and functionality of Kotlin's Sequence class into the Python
ecosystem. With an emphasis on functional programming paradigms, Kothon enables Python developers to leverage
lazy-evaluated sequences, allowing for efficient and expressive data processing pipelines.FeaturesFunctional Programming: Embrace functional programming with a rich set of operators
likemap,filter,reduce, and much more, enabling you to write more declarative and concise code.Strongly Typed: Leveraging Python's type hints for clearer, more robust code.Lazy Evaluation: Kothon sequences are evaluated lazily, meaning computations are deferred until the value is
needed, enhancing performance especially for large datasets.Interoperability: Seamlessly integrate with existing Python codebases, enjoying the benefits of Kotlin-like
sequences without disrupting your current workflow.Easy to Use: Kothon's API is designed to be intuitive for both Python and Kotlin developers, ensuring a smooth
learning curve.InstallationTo install Kothon, simply run the following command in your terminal:pipinstallkothonQuick StartHere's a quick example to get you started with Kothon:fromkothonimportSeq# Create a Kothon sequenceseq=Seq(range(10))# Apply some functional operationsresult=seq\.filter(lambdax:x%2==0)\.map(lambdax:x*2)\.to_list()print(result)# Output: [0, 4, 8, 12, 16]Custom FunctionsYou can easily extend theSeqclass to include custom functionality tailored to your specific needs. This is achieved by subclassingSeqand adding your own methods to the new subclass.>>>importkothon>>>fromtypingimportTypeVar,Generic>>>T=TypeVar("T")>>>>>>classSeq(kothon.Seq[T],Generic[T]):...defelement_at(self,index:int)->T:..."""Retrieves an element at the specified index from the sequence."""...try:...returnself.drop(index).first()...exceptValueError:...raiseIndexError("Index out of bounds")>>>>>>Seq(['a','b','c','d']).element_at(2)'c'>>>Existing functions inSeqfilterFilters elements based on a predicate.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3,4,5])>>>seq.filter(lambdax:x%2==0).to_list()[2,4]>>>filter_not_noneFilters outNonevalues from the sequence.>>>fromkothonimportSeq>>>>>>seq=Seq([1,None,2,None,3])>>>seq.filter_not_none().to_list()[1,2,3]>>>filter_is_instanceFilters elements of the sequence based on their type.>>>fromkothonimportSeq>>>>>>seq=Seq([1,'two',3,'four',5])>>>seq.filter_is_instance(str).to_list()['two','four']>>>mapApplies a function to each element in the sequence.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3])>>>seq.map(lambdax:x*x).to_list()[1,4,9]>>>map_not_noneApplies a function to each element and filters outNoneresults.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3,4])>>>seq.map_not_none(lambdax:x*2ifx%2==0elseNone).to_list()[4,8]>>>flat_mapApplies a function to each element that returns an iterable and flattens the result.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3])>>>seq.flat_map(lambdax:[x,-x]).to_list()[1,-1,2,-2,3,-3]>>>flattenFlattens a sequence of iterables into a single sequence.>>>fromkothonimportSeq>>>>>>seq=Seq([[1,2],[3,4],[5]])>>>seq.flatten().to_list()[1,2,3,4,5]>>>associateTransforms elements into key-value pairs and aggregates them into a dictionary.>>>fromkothonimportSeq>>>>>>seq=Seq(["a","bb","ccc"])>>>seq.associate(lambdax:(x,len(x))){'a':1,'bb':2,'ccc':3}>>>associate_byCreates a dictionary from the sequence by determining keys using a specified key selector function.>>>fromkothonimportSeq>>>>>>seq=Seq(["apple","banana","cherry"])>>>seq.associate_by(lambdax:x[0]){'a':'apple','b':'banana','c':'cherry'}>>>associate_withCreates a dictionary from the sequence with elements as keys and values determined by a value selector function.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3])>>>seq.associate_with(lambdax:x*x){1:1,2:4,3:9}>>>group_byGroups elements based on a key function.>>>fromkothonimportSeq>>>>>>seq=Seq(["one","two","three"])>>>seq.group_by(len){3:['one','two'],5:['three']}>>>to_listConverts the sequence to a list.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3])>>>seq.to_list()[1,2,3]>>>to_setConverts the sequence to a set.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,2,3,3])>>>seq.to_set(){1,2,3}>>>allChecks if all elements satisfy a condition.>>>fromkothonimportSeq>>>>>>seq=Seq([2,4,6])>>>seq.all(lambdax:x%2==0)True>>>seq.all(lambdax:x>5)False>>>noneChecks if no elements satisfy a condition.>>>fromkothonimportSeq>>>>>>seq=Seq([1,3,5])>>>seq.none(lambdax:x%2==0)True>>>seq.none(lambdax:x<5)False>>>anyChecks if any elements satisfy a condition.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3])>>>seq.any(lambdax:x%2==0)True>>>seq.any(lambdax:x>5)False>>>maxFinds the maximum element.>>>fromkothonimportSeq>>>>>>seq=Seq([1,3,2])>>>seq.max()3>>>max_or_noneFinds the maximum element, or returnsNonefor an empty sequence.>>>fromkothonimportSeq>>>>>>seq=Seq([1,3,2])>>>seq.max_or_none()3>>>seq=Seq([])>>>seq.max_or_none()>>>max_byFinds the element which maximizes a specified function.>>>fromkothonimportSeq>>>>>>seq=Seq(['a','abc','ab'])>>>seq.max_by(len)'abc'>>>max_by_or_noneLikemax_by, but returnsNonefor an empty sequence.>>>fromkothonimportSeq>>>>>>seq=Seq(['a','abc','ab'])>>>seq.max_by_or_none(len)'abc'>>>seq=Seq([])>>>seq.max_by_or_none(len)>>>minFinds the minimum element.>>>fromkothonimportSeq>>>>>>seq=Seq([3,1,2])>>>seq.min()1>>>min_or_noneFinds the minimum element, or returnsNonefor an empty sequence.>>>fromkothonimportSeq>>>>>>seq=Seq([1,3,2])>>>seq.min_or_none()1>>>seq=Seq([])>>>seq.min_or_none()>>>min_byFinds the element which minimizes a specified function.>>>fromkothonimportSeq>>>>>>seq=Seq(['abc','a','ab'])>>>seq.min_by(len)'a'>>>min_by_or_noneLikemin_by, but returnsNonefor an empty sequence.>>>fromkothonimportSeq>>>>>>seq=Seq(['abc','a','ab'])>>>seq.min_by_or_none(len)'a'>>>seq=Seq([])>>>seq.min_by_or_none(len)>>>singleReturns the single element of the sequence, and throws an error if the sequence does not contain exactly one element.>>>fromkothonimportSeq>>>>>>Seq([9]).single()9>>># Seq([]).single()  # ERROR>>># Seq([1, 2]).single()  # ERROR>>>single_or_noneReturns the single element of the sequence, orNoneif the sequence is empty. Throws an error if the sequence contains more than one element.>>>fromkothonimportSeq>>>>>>Seq([9]).single_or_none()9>>>Seq([]).single_or_none()>>>Seq([1,2]).single_or_none()>>>firstReturns the first element of the sequence. Throws an error if the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([7,8,9]).first()7>>># Seq([]).first()  # ERROR>>>first_or_noneReturns the first element of the sequence, orNoneif the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([7,8,9]).first_or_none()7>>>Seq([]).first_or_none()>>>lastReturns the last element of the sequence. Throws an error if the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([7,8,9]).last()9>>># Seq([]).last()  # ERROR>>>last_or_noneReturns the last element of the sequence, orNoneif the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([7,8,9]).last_or_none()9>>>Seq([]).last_or_none()>>>dropReturns a new sequence with the firstnelements removed.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4]).drop(2).to_list()[3,4]>>>drop_whileReturns a new sequence by dropping elements as long as the predicate is true.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3,4,1])>>>seq.drop_while(lambdax:x<3).to_list()[3,4,1]>>>takeReturns a new sequence containing the firstnelements.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4]).take(2).to_list()[1,2]>>>take_whileReturns a new sequence by taking elements as long as the predicate is true.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3,4,1])>>>seq.take_while(lambdax:x<3).to_list()[1,2]>>>sortedReturns a new sequence with elements sorted in ascending order.>>>fromkothonimportSeq>>>>>>Seq([3,1,4]).sorted().to_list()[1,3,4]>>>sorted_bySorts elements by a specified key function.>>>fromkothonimportSeq>>>>>>seq=Seq(['apple','banana','cherry'])>>>seq.sorted_by(lambdax:x[0]).to_list()['apple','banana','cherry']>>>sorted_descReturns a new sequence with elements sorted in descending order.>>>fromkothonimportSeq>>>>>>Seq([3,1,4]).sorted_desc().to_list()[4,3,1]>>>sorted_by_descSorts elements by a specified key function in descending order.>>>fromkothonimportSeq>>>>>>seq=Seq(['apple','banana','cherry'])>>>seq.sorted_by_desc(lambdax:x[0]).to_list()['cherry','banana','apple']>>>chunkedSplits the sequence into chunks of the specified size.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4,5]).chunked(2).to_list()[[1,2],[3,4],[5]]>>>enumerateAdds an index to each element of the sequence.>>>fromkothonimportSeq>>>>>>Seq(['a','b','c']).enumerate().to_list()[(0,'a'),(1,'b'),(2,'c')]>>>shuffledReturns a new sequence with elements shuffled in random order.>>>importrandom>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3,4,5])>>>rng=random.Random(42)# custom pseudo-random number generator, Optional>>>seq.shuffled(rng).to_list()[4,2,3,5,1]>>>reduceReduces the sequence to a single value by applying a binary operation. Throws an error if the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4]).reduce(lambdax,y:x+y)10>>>reduce_or_noneLikereduce, but returnsNonefor an empty sequence.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4]).reduce_or_none(lambdax,y:x+y)10>>>Seq([]).reduce_or_none(lambdax,y:x+y)>>>sumSums the elements in the sequence. Throws an error if the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4]).sum()10>>>sum_or_noneCalculates the sum of all elements in the sequence, or returnsNoneif the sequence is empty.>>>fromkothonimportSeq>>>>>>Seq([1,2,3,4]).sum_or_none()10>>>Seq([]).sum_or_none()>>>distinctReturns a new sequence with distinct elements.>>>fromkothonimportSeq>>>>>>Seq([1,2,2,3,3]).distinct().to_list()[1,2,3]>>>distinct_byReturns a new sequence with elements that are distinct based on the specified key function.>>>fromkothonimportSeq>>>>>>seq=Seq(['apple','banana','apricot'])>>>seq.distinct_by(lambdax:x[0]).to_list()['apple','banana']>>>for_eachApplies an action to each element of the sequence.>>>fromkothonimportSeq>>>>>>result=[]>>>Seq([1,2,3]).for_each(lambdax:print(x))123>>>join_to_stringConcatenates elements of the sequence into a single string with specified separators and optional prefix/suffix.>>>fromkothonimportSeq>>>>>>seq=Seq(['apple','banana','cherry'])>>>seq.join_to_string(separator=", ",prefix="[",suffix="]")'[apple, banana, cherry]'>>>partitionSplits the sequence into two sequences based on a predicate. The first sequence contains elements for which the predicate is true, and the second contains elements for which it is false.>>>fromkothonimportSeq>>>>>>seq=Seq([1,2,3,4,5])>>>true_part,false_part=seq.partition(lambdax:x%2==0)>>>true_part.to_list()[2,4]>>>false_part.to_list()[1,3,5]>>>ContributingWe welcome contributions! If you have improvements or bug fixes, please feel free to create a pull request.AcknowledgmentsKothon is inspired by the Kotlin Sequence class and the broader functional programming paradigm. We are grateful to the
Kotlin community for their innovative work, which has inspired the creation of this library.