| Name | istr-python JSON |
| Version |
1.0.12.post0
JSON |
| download |
| home_page | None |
| Summary | istr - strings you can count on |
| upload_time | 2024-08-18 12:43:09 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.7 |
| license | None |
| keywords |
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
<img src="https://www.salabim.org/istr/istr_logo.png" width=500>
### Introduction
The `istr` module makes it possible to use strings as if they were integers.
This can be very handy for solving puzzles, but also for other purposes.
For instance the famous send more money puzzle, where each letter has to be replaced by a unique digit (0-9)
```
S E N D
M O R E
--------- +
M O N E Y
```
can be nicely, albeit not very efficient, coded as:
```
import itertools
from istr import istr
for s, e, n, d, m, o, r, y in istr(itertools.permutations(range(10), 8)):
if m and ((s|e|n|d) + (m|o|r|e) == (m|o|n|e|y)):
print(f' {s|e|n|d}')
print(f' {m|o|r|e}')
print('-----')
print(f'{m|o|n|e|y}')
```
Of, if we want to add all the digits in a string:
```
sum_digits = sum(istr('9282334')) # answer 31
```
And the module is a demonstration of extending a class (str) with extra and changed functionality.
### Installation
Installing istr with pip is easy.
```
$ pip install istr-python
```
or when you want to upgrade,
```
$ pip install istr-python --upgrade
```
Alternatively, istr.py can be just copied into you current work directory from GitHub (https://github.com/salabim/istr).
No dependencies!
### Usage
#### Start
Just start with
```
from istr import istr
```
#### Use istr as int
We can define an istr:
```
four = istr('4')
five = istr('5')
```
The variables `four` and `five` can now be used as if they were int:
```
twenty = four * five
```
, after which x is `istr('20')`
The same can be done with
```
twenty = 4 * five
```
or
```
twenty = four * 5
```
And now `twenty` can be used as if it was an int as well. So
```
twenty - four
```
is `istr('16')`
We can do all the usual arithmetic operations on istrs, e.g.
```
-four + (twenty / 2)
```
is `istr('6')`
And we can test for equality. So:
```
twenty == 20
```
is True.
But istrs are also strings. So
```
twenty == '20'
```
is also True!
For the order comparisons (<=, <, >, >=), the istr is always interpreted as an int.
That means that
```
twenty < 30
twenty >= '10' # here '10' is converted to the integer 10 for the comparison
```
are both`True`.
In contrast to an ordinary string
```
print(four + five)
```
prints `9`, as istr are treated as ints (if possible).
Please note that `four` could have also been initialized with
```
four = istr(4)
```
or even
```
four, five = istr(4, 5)
```
##### Important
>
> All calculations are strictly integer calculations. That means that if a float or decimal variable is ever produced it will be converted to an int.
> Also divisions are always floor divisions!
#### Use istr as str
We should realize that istrs are in fact strings.
In order to concatenate two istrs (or an istr and a str), we cannot use the `+` operator (remember `four + five` is `istr('9')`).
In order to concatenate istrs, we use the or operator (`|`). So
```
four | five
```
will be `istr(`45`).
And
```
(four | five) / 3
```
is `istr('9')`.
In order to repeat a string in the usual sense, you cannot use the `*` operator (remember `3 * four` is `istr('12')`.
In order to repeat we use the matrix multiplication operator (`@`). So
`3 @ four`
is `istr('444')`
And
```four @ 3```
is also `istr('444')`
##### Note
>
> It is not allowed to use the `@` operator for two istrs. So, `four @ five` raises a TypeError.
#### istr that can't be interpreted as an int
Although usualy istrs are to be interpreted as an int, that's not a requirement.
So
```
istr('abc')
```
or
```
istr('1,2,3')
```
are perfectly acceptable.
But, we can't do any arithmetic or comparison with them.
If we try
```
istr('abc') + 5
```
a `TypeError` will be raised.
That holds for any arithmetic we try.
If we want to test if an istr can be interpreted (and thus used in an arithmetic and comparison expression). we can use the `is_int()` method. So
```ìstr(20).is_int()```
is `True`, whereas
```ìstr('abc').is_int()```
is `False`.
The `bool` operator works normally on the integer value of an istr. So
`bool(istr('0'))` ==> `False`
`bool(istr('1'))` ==> `True`
But if the istr can't be interpreted as an int, the string value will be used to test. So
`bool(istr('abc'))` ==> `True`
`bool(istr(''))` ==> `False`
#### Other operators
For the `in` operator, an istr is treated as an ordinary string, although it is possible to use ints as well:
```
'34' in istr(1234)
34 in istr(1234)
```
On the left hand side an istr is always treated as a string:
```
istr(1234) in '01234566890ABCDEF'
```
Sorting a list of istrs is based on the integer value, not the string. So
```
' '.join(sorted('1 3 2 4 5 6 11 7 9 8 10 12 0'.split()))
```
is
```
'0 1 10 11 2 3 4 5 6 7 8 9'
```
,whereas
```
' '.join(sorted(istr('1 3 2 4 5 6 11 7 9 8 10 12 0'.split()))
```
is
```
'0 1 2 3 4 5 6 7 8 9 10 11'
```
#### Using values that are neither string nor numeric to initialize istr
Apart from with numeric (to be interpreted as an int) or str, istr can be initialized with
several other types:
- if a dict (or subtype of dict), the same type dict will be returned with all *values* istr'ed
```
istr({'one': 1, 'two':2}) ==> {'one': istr('1'), 'two': istr('2')}
```
- if an iterator, the iterator will be mapped with istr
```
mapped = (i for i in istr((i for i in range(2))))
print(mapped)
print(list(mapped))
```
this wil print something like
```
<generator object <genexpr> at 0x000002A10DE569B0>
[istr('0'), istr('1')]
```
- if an iterable, the same type will be returned with all elements istr'ed
```
istr([0, 1, 4]) ==> [istr('0'), istr('1'), istr('4')]
istr((0, 1, 4)) ==> (istr('0'), istr('1'), istr('4'))
istr({0, 1, 4}) ==> `{istr('4'), istr('0'), istr('1')} # or similar
```
- if a range, an istr.range instance will be returned
```
istr(range(3)) ==> istr.range(3)
list(istr(range(3))) ==> [istr('0'), istr('1'), istr('2')]
len(istr(range(3))) ==> 3
```
- if an istr.range instance, the same istr.range will be returned
```
istr(istr.range(5)) ==> istr.range(5)
```
- if an istr, the same istr will be returned
```
istr(istr('4')) ==> istr ('4')
```
#### More than one parameter for istr
It is possible to give more than one parameter, in which case a tuple
of the istrs of the parameters will be returned, which can be handy
to unpack multiple values, e.g.
```
a, b, c = istr(5, 6, 7) ==> a=istr('5') , b=istr('6'), c=istr('7')
```
#### test for even/odd
It is possible to test for even/odd (provided the istr can be interpreted as an int) with the `is_even` and `is_odd` method, e.g.
```
istr(4).is_even()) ==> True
istr(5).is_odd()) ==> True
```
It is also possible to test for even/odd of an ordinary int:
```
istr.is_even(4) ==> True
istr.is_odd(5) ==> True
```
#### test for square
It is possible to test whether the value is a perfect square (provided the istr can be interpreted as an int) with the `is_square` method, e.g.
```
istr(4).is_square() ==> True
istr(5).is_square()) ==> False
```
It is also possible to test for square of an ordinary int:
```
istr.is_square(4) ==> True
istr.is_square(5) ==> False
```
#### test for prime
It is possible to test whether the value is a prime number (provided the istr can be interpreted as an int) with the `is_prime` method, e.g.
```
istr(4).is_prime() ==> False
istr(5).is_prime()) ==> True
```
It is also possible to test for prime of an ordinary int:
```
istr.is_prime(4) ==> False
istr.is_prime(5) ==> True
```
#### test for divisibility
It is possible to test whether an istr is divisible by a given value with the `is_divisible_by method,` e.g.
```
istr(18).is_divisible_by(3) ==> True
istr(18).is_divisible_by(istr(3)) ==> True
istr(19).is_divisible_by(3) ==> False
istr(19).is_divisible_by(istr(3)) == False
```
It is also possible to test for divisibility of an ordinary int:
```
istr.is_divisible(18, 3) ==> True
istr.is_divisible(19, 3) ==> False
```
#### test whether all characters are distinct
With the `all_distinct` method, it is possible to test whether all characters are distinct (i.e. no character appears more than once).
```
istr('01234').all_distict() ==> True
istr('012340').all_distict() ==> False
n98 = istr(98)
n100 = n98 + 2
istr(n98).all_distinct() ==> True
istr(n100).all_distinct() ==> False
```
#### reverse an istr
The method `reversed()` will return an istr with the reversed content:
```
istr(456).reversed() ==> istr('654')
istr('0456').reversed() ==> istr('6540')
```
The same can -of course- be achieved with
```
istr(456)[::-1] ==> istr('654')
istr('0456')[::-1] ==> istr('6540')
```
##### Note
>
> It is possible to reverse a negative istr, but the result can't be interpreted as an int anymore.
>
> ```
> istr(-456).reversed() + 3 ==> TypeError
> ```
#### enumerate with istrs
The `istr.enumerate` class method can be used just as the built-in enumerate function.
The iteration counter however is an istr rather than an int. E.g.
```
for i, c in istr.enumerate('abc'):
print(f'{repr(i)} {c}')
```
prints
```
istr('0') a
istr('1') b
istr('2') c
```
#### itertools with istrs
All methods in itertools are also available directly from istr.
Note that the result is istr-ed (apart from groupby and tee).
The following class methods are supported (provided their counterpart exists in the installed Python version's itertools):
- istr.accumulate
- istr.chain
- istr.combinations
- istr.combinations_with_replacement
- istr.compress
- istr.count
- istr.cycle
- istr.dropwhile
- istr.filterfalse
- istr.groupby (not istr-ed)
- istr.islice
- istr.pairwise
- istr.permutations
- istr.product
- istr.repeat
- istr.starmap
- istr.takewhile
- istr.tee (not istr-ed)
- istr.zip_longest
This can be handy as these methods don't have to be imported from itertools anymore.
All methods have exactly the same (optional) parameters as their itertools counterpart.
For example:
```
list(istr.repeat(1, 4)) ==> [istr('1'), istr('1'), istr('1'), istr('1')]
next(istr.count(3)) ==> istr('3')
```
One more example:
```
for t in istr.permutations(range(3)):
print(t)
```
results in
```
(istr('0'), istr('1'), istr('2'))
(istr('0'), istr('2'), istr('1'))
(istr('1'), istr('0'), istr('2'))
(istr('1'), istr('2'), istr('0'))
(istr('2'), istr('0'), istr('1'))
(istr('2'), istr('1'), istr('0'))
```
#### concatenate an iterable
The `istr.concat` method can be useful to map all items of an iterable
to `istr` and then concatenate these.
`
```
list(istr.concat(((1,2),(3,4))) ==> istr([12,34])
list(istr.concat(itertools.permutations(range(3),2))) ==>
[istr('01'), istr('02'), istr('10'), istr('12'), istr('20'), istr('21')]
```
#### generate istr with digits
The class method `digits` can be used to return an istr of digits according to a given specification.
The method takes either no or a number of arguments.
If no arguments are given, the result will be `istr('0123456789')`.
The given argument(s) result in a range of digits.
- `<n>` ==> n
- `<n-m>` ==> n, n+1, ..., m
- `-n>` ==> 0, 1, ... n
- `n->` ==> n, n+1, ..., 9 if n is numeric (0-9), n, n+1, ... Z if n is a letter
- `'-'` ==> 0, 1, ..., 9
- `''` ==> 0, 1, ..., 9
(n and m must be digits between 0 and 9 or letters letters between A and Z)
When no stop value is specified, it will be
* 9 if the start value is between 0 and 9
* Z if the start value is between A and Z
The final result is an istr composed of the given range(s).
Here are some examples:
```
istr.digits() ==> istr('0123456789')
istr.digits('') ==> istr('0123456789')
istr.digits('1') ==> istr('1')
istr.digits('3-') ==> istr('3456789')
istr.digits('-3') ==> istr('0123')
istr('1-4', '6', '8-9') ==> istr('1234689')
istr('1', '1-2', '1-3') ==> istr('11213')
istr.digits('-z') ==> istr('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')
istr.digits('A-F') ==> istr('ABCDEF')
istr.digits('C') ==> istr('C')
istr.digits('3-') ==> istr('34567879')
istr.digits('X-') ==> istr('XYZ')
```
#### Subclassing istr
When a class is derived from istr, all methods will return that newly derived class.
E.g.
```
class jstr(istr):
...
print(repr(jstr(4) * jstr(5)))
```
will print `jstr('20')`
#### Changing the way repr works
It is possible to control the way an `istr` instance will be repr'ed.
By default, `istr(5)` is represented as `istr('5')`.
With the `istr.repr_mode()` context manager, that can be changed:
```
with istr.repr_mode('str'):
five = istr(5)
print(repr(five))
with istr.repr_mode('int'):
five = istr(5)
print(repr(five))
with istr.repr_mode('istr'):
five = istr(5)
print(repr(five))
```
This will print
```
'5'
5
istr('5')
```
If the repr_mode is `'int'` and the istr can't be interpreted as an int the string `?` will be returned:
```
with istr.repr_mode('int'):
abc = istr('abc')
print(repr(abc))
```
This will print
```
?
```
##### Note
>
> The way an `istr` is represented is determined at initialization.
It is also possible to set the repr mode without a context manager:
```
istr.repr_mode('str')
five = istr('5')
print(repr(five))
```
This will print
```
'5'
```
Finally, the current repr mode can be queried with `istr.repr_mode()`. So upon start:
```
print(repr(istr.repr_mode()))
```
will output `istr`.
#### Changing the base system
By default, `istr` works in base 10. However it is possible to change the base system with the `istr.base()` context manager / method.
Any base between 2 and 36 may be used.
Note that the integer is **always** stored in base 10 mode, but the string
representation will reflect the chosen base (at time of initialization).
Some examples:
```
with istr.base(16):
a = istr('7fff')
print(int(a))
b = istr(127)
print(repr(b))
```
This will result in
```
32767
istr('7F')
```
All calculations are done in the decimal 10 base system.
Note that the way an `istr` is interpreted is determined at initialization.
It is also possible to set the repr mode without a context manager:
```
istr.base(16)
print(int(istr('7fff')))
```
This will print
```
32767
```
Finally, the current base can be queried with `istr.base()`, so upon start:
```
print(istr.base())
```
will result in `10`.
#### Changing the format of the string
When an istr is initialized with a string the istr will be always stored as such.
```
repr('4')) ==> istr('4')
repr(' 4')) ==> istr(' 4')
repr('4 ')) ==> istr('4 ')
```
For initializing with an int (or other numeric) value, the string is by default simply the str representation
```
repr(4)) ==> istr('4')
```
With the `istr.int_format()` context manager this behavior can be changed.
If the format specifier is a number, most likely a single digit, that
will be the minimum number of characters in the string:
```
with istr.int_format('3'):
print(repr(istr(1)))
print(repr(istr(12)))
print(repr(istr(123)))
print(repr(istr(1234)))
```
will print
```
istr(' 1')
istr(' 12')
istr('123')
istr('1234')
```
If the string starts with a `0`, the string will be zero filled:
```
with istr.int_format('03'):
print(repr(istr(1)))
print(repr(istr(12)))
print(repr(istr(123)))
print(repr(istr(1234)))
```
will print
```
istr('001')
istr('012')
istr('123')
istr('1234')
```
##### Note
>
> For bases other than 10, the string will never be reformatted!
### Overview of operations
The table below shows whether the string or the int version of istr is applied.
```
operator/function int str Example
-----------------------------------------------------------------------------------------
+ x istr(20) + 3 ==> istr('23')
_ x istr(20) - 3 ==> istr('17')
* x istr(20) * 3 ==> istr('60')
/ x istr(20) / 3 ==> istr('6')
// x istr(20) // 3 ==> istr('6')
% x istr(20) % 3 ==> istr('2')
divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
** x istr(2) ** 3 ==> istr('8')
<=, <, >, >= x istr('100') > istr('2') ==> True
abs x abs(istr(-20)) ==> istr('20')
== x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
bool x x *) bool(istr(' 0 ')) ==> False | istr('') ==> False
@ x istr(20) @ 3 ==> istr('202020')
| x istr(20) | '5' ==> istr('205')
slicing x istr(12345)[1:3] ==> istr('23')
iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
len x len(istr(' 20 ')) ==> 4
count x istr(100).count('0') ==> 2
index x istr(' 100 ').index('0') ==> 2
split x istr('1 2').split() ==> (istr('1'), istr('2'))
string format x f"|{istr(1234):6}|" ==> '|1234 |'
other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
istr('aAbBcC').islower() ==> False
istr(' abc ').strip() ==> istr('abc')
...
-----------------------------------------------------------------------------------------
*) str is applied if is_int() is False
```
### Test script
There's an extensive pytest script in the `\tests` directory.
This script also shows clearly the ways istr can be used, including several edge cases. Highly recommended to have a look at.
### Badges
  
 

Raw data
{
"_id": null,
"home_page": null,
"name": "istr-python",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": null,
"author": null,
"author_email": "Ruud van der Ham <rt.van.der.ham@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/7f/5f/7a087d543127ee10582ca5cc17215c7093ccf45fe5488d77b1164fe88aca/istr_python-1.0.12.post0.tar.gz",
"platform": null,
"description": " <img src=\"https://www.salabim.org/istr/istr_logo.png\" width=500>\r\n\r\n### Introduction\r\n\r\nThe `istr` module makes it possible to use strings as if they were integers.\r\n\r\nThis can be very handy for solving puzzles, but also for other purposes.\r\nFor instance the famous send more money puzzle, where each letter has to be replaced by a unique digit (0-9)\r\n\r\n```\r\n S E N D\r\n M O R E\r\n--------- +\r\nM O N E Y\r\n```\r\ncan be nicely, albeit not very efficient, coded as:\r\n```\r\nimport itertools\r\nfrom istr import istr\r\n\r\nfor s, e, n, d, m, o, r, y in istr(itertools.permutations(range(10), 8)):\r\n if m and ((s|e|n|d) + (m|o|r|e) == (m|o|n|e|y)):\r\n print(f' {s|e|n|d}')\r\n print(f' {m|o|r|e}')\r\n print('-----')\r\n print(f'{m|o|n|e|y}')\r\n```\r\n\r\nOf, if we want to add all the digits in a string:\r\n\r\n```\r\nsum_digits = sum(istr('9282334')) # answer 31\r\n```\r\n\r\nAnd the module is a demonstration of extending a class (str) with extra and changed functionality.\r\n\r\n### Installation\r\nInstalling istr with pip is easy.\r\n```\r\n$ pip install istr-python\r\n```\r\nor when you want to upgrade,\r\n```\r\n$ pip install istr-python --upgrade\r\n```\r\nAlternatively, istr.py can be just copied into you current work directory from GitHub (https://github.com/salabim/istr).\r\n\r\nNo dependencies!\r\n\r\n### Usage\r\n#### Start\r\n\r\nJust start with\r\n\r\n```\r\nfrom istr import istr\r\n```\r\n\r\n#### Use istr as int\r\n\r\nWe can define an istr:\r\n```\r\nfour = istr('4')\r\nfive = istr('5')\r\n```\r\nThe variables `four` and `five` can now be used as if they were int:\r\n\r\n```\r\ntwenty = four * five\r\n```\r\n, after which x is `istr('20')`\r\n\r\nThe same can be done with\r\n\r\n```\r\ntwenty = 4 * five\r\n```\r\n\r\nor\r\n\r\n```\r\ntwenty = four * 5\r\n```\r\n\r\nAnd now `twenty` can be used as if it was an int as well. So\r\n\r\n```\r\ntwenty - four\r\n```\r\n\r\nis `istr('16')`\r\n\r\nWe can do all the usual arithmetic operations on istrs, e.g.\r\n\r\n```\r\n-four + (twenty / 2)\r\n```\r\n\r\nis `istr('6')`\r\n\r\nAnd we can test for equality. So:\r\n\r\n```\r\ntwenty == 20\r\n```\r\nis True.\r\n\r\nBut istrs are also strings. So\r\n\r\n```\r\ntwenty == '20'\r\n```\r\n\r\nis also True!\r\n\r\nFor the order comparisons (<=, <, >, >=), the istr is always interpreted as an int.\r\n\r\nThat means that \r\n```\r\ntwenty < 30\r\ntwenty >= '10' # here '10' is converted to the integer 10 for the comparison\r\n```\r\nare both`True`.\r\n\r\nIn contrast to an ordinary string\r\n```\r\nprint(four + five)\r\n```\r\nprints `9`, as istr are treated as ints (if possible).\r\n\r\nPlease note that `four` could have also been initialized with\r\n```\r\nfour = istr(4)\r\n```\r\nor even\r\n```\r\nfour, five = istr(4, 5)\r\n```\r\n\r\n##### Important\r\n>\r\n> All calculations are strictly integer calculations. That means that if a float or decimal variable is ever produced it will be converted to an int.\r\n> Also divisions are always floor divisions!\r\n\r\n#### Use istr as str\r\n\r\nWe should realize that istrs are in fact strings.\r\n\r\nIn order to concatenate two istrs (or an istr and a str), we cannot use the `+` operator (remember `four + five` is `istr('9')`).\r\n\r\nIn order to concatenate istrs, we use the or operator (`|`). So\r\n\r\n```\r\nfour | five\r\n```\r\nwill be `istr(`45`).\r\n\r\nAnd\r\n```\r\n(four | five) / 3\r\n```\r\nis `istr('9')`.\r\n\r\nIn order to repeat a string in the usual sense, you cannot use the `*` operator (remember `3 * four` is `istr('12')`. \r\n\r\nIn order to repeat we use the matrix multiplication operator (`@`). So\r\n\r\n `3 @ four`\r\n\r\n is `istr('444')`\r\n\r\nAnd \r\n\r\n```four @ 3```\r\n\r\nis also `istr('444')`\r\n\r\n##### Note\r\n\r\n>\r\n> It is not allowed to use the `@` operator for two istrs. So, `four @ five` raises a TypeError.\r\n#### istr that can't be interpreted as an int\r\n\r\n\r\nAlthough usualy istrs are to be interpreted as an int, that's not a requirement.\r\n\r\nSo\r\n\r\n```\r\nistr('abc')\r\n```\r\n\r\nor\r\n\r\n```\r\nistr('1,2,3')\r\n```\r\n\r\nare perfectly acceptable.\r\n\r\nBut, we can't do any arithmetic or comparison with them. \r\n\r\nIf we try\r\n\r\n```\r\nistr('abc') + 5\r\n```\r\n\r\na `TypeError` will be raised.\r\n\r\nThat holds for any arithmetic we try.\r\n\r\nIf we want to test if an istr can be interpreted (and thus used in an arithmetic and comparison expression). we can use the `is_int()` method. So\r\n\r\n```\u00ecstr(20).is_int()```\r\n\r\nis `True`, whereas\r\n\r\n```\u00ecstr('abc').is_int()```\r\n\r\nis `False`.\r\n\r\n\r\n\r\nThe `bool` operator works normally on the integer value of an istr. So\r\n\r\n`bool(istr('0'))` ==> `False`\r\n`bool(istr('1'))` ==> `True`\r\n\r\nBut if the istr can't be interpreted as an int, the string value will be used to test. So\r\n\r\n`bool(istr('abc'))` ==> `True`\r\n`bool(istr(''))` ==> `False`\r\n\r\n#### Other operators\r\n\r\nFor the `in` operator, an istr is treated as an ordinary string, although it is possible to use ints as well:\r\n\r\n```\r\n'34' in istr(1234)\r\n34 in istr(1234)\r\n\r\n```\r\nOn the left hand side an istr is always treated as a string:\r\n```\r\nistr(1234) in '01234566890ABCDEF'\r\n```\r\n\r\nSorting a list of istrs is based on the integer value, not the string. So\r\n\r\n```\r\n' '.join(sorted('1 3 2 4 5 6 11 7 9 8 10 12 0'.split()))\r\n```\r\n\r\nis\r\n\r\n```\r\n'0 1 10 11 2 3 4 5 6 7 8 9'\r\n```\r\n\r\n,whereas\r\n\r\n```\r\n' '.join(sorted(istr('1 3 2 4 5 6 11 7 9 8 10 12 0'.split()))\r\n```\r\n\r\nis \r\n\r\n```\r\n'0 1 2 3 4 5 6 7 8 9 10 11'\r\n```\r\n#### Using values that are neither string nor numeric to initialize istr\r\n\r\nApart from with numeric (to be interpreted as an int) or str, istr can be initialized with\r\nseveral other types:\r\n\r\n\r\n- if a dict (or subtype of dict), the same type dict will be returned with all *values* istr'ed\r\n ```\r\n istr({'one': 1, 'two':2}) ==> {'one': istr('1'), 'two': istr('2')}\r\n ```\r\n\r\n- if an iterator, the iterator will be mapped with istr\r\n ```\r\n mapped = (i for i in istr((i for i in range(2))))\r\n print(mapped)\r\n print(list(mapped))\r\n ```\r\n this wil print something like\r\n ```\r\n <generator object <genexpr> at 0x000002A10DE569B0>\r\n [istr('0'), istr('1')]\r\n ```\r\n\r\n- if an iterable, the same type will be returned with all elements istr'ed\r\n\r\n```\r\n istr([0, 1, 4]) ==> [istr('0'), istr('1'), istr('4')]\r\n istr((0, 1, 4)) ==> (istr('0'), istr('1'), istr('4'))\r\n istr({0, 1, 4}) ==> `{istr('4'), istr('0'), istr('1')} # or similar \r\n```\r\n\r\n- if a range, an istr.range instance will be returned\r\n \r\n```\r\n istr(range(3)) ==> istr.range(3)\r\n list(istr(range(3))) ==> [istr('0'), istr('1'), istr('2')]\r\n len(istr(range(3))) ==> 3\r\n```\r\n\r\n- if an istr.range instance, the same istr.range will be returned\r\n ```\r\n istr(istr.range(5)) ==> istr.range(5)\r\n ```\r\n\r\n\r\n- if an istr, the same istr will be returned\r\n\r\n ```\r\n istr(istr('4')) ==> istr ('4')\r\n ```\r\n\r\n#### More than one parameter for istr\r\nIt is possible to give more than one parameter, in which case a tuple\r\nof the istrs of the parameters will be returned, which can be handy\r\nto unpack multiple values, e.g.\r\n\r\n```\r\na, b, c = istr(5, 6, 7) ==> a=istr('5') , b=istr('6'), c=istr('7') \r\n```\r\n\r\n#### test for even/odd\r\nIt is possible to test for even/odd (provided the istr can be interpreted as an int) with the `is_even` and `is_odd` method, e.g.\r\n\r\n```\r\nistr(4).is_even()) ==> True\r\nistr(5).is_odd()) ==> True\r\n```\r\nIt is also possible to test for even/odd of an ordinary int:\r\n```\r\nistr.is_even(4) ==> True\r\nistr.is_odd(5) ==> True\r\n```\r\n#### test for square\r\n\r\nIt is possible to test whether the value is a perfect square (provided the istr can be interpreted as an int) with the `is_square` method, e.g.\r\n\r\n```\r\nistr(4).is_square() ==> True\r\nistr(5).is_square()) ==> False\r\n```\r\nIt is also possible to test for square of an ordinary int:\r\n```\r\nistr.is_square(4) ==> True\r\nistr.is_square(5) ==> False\r\n```\r\n#### test for prime\r\n\r\nIt is possible to test whether the value is a prime number (provided the istr can be interpreted as an int) with the `is_prime` method, e.g.\r\n\r\n```\r\nistr(4).is_prime() ==> False\r\nistr(5).is_prime()) ==> True\r\n```\r\nIt is also possible to test for prime of an ordinary int:\r\n\r\n```\r\nistr.is_prime(4) ==> False\r\nistr.is_prime(5) ==> True\r\n```\r\n#### test for divisibility\r\n\r\nIt is possible to test whether an istr is divisible by a given value with the `is_divisible_by method,` e.g.\r\n\r\n```\r\nistr(18).is_divisible_by(3) ==> True\r\nistr(18).is_divisible_by(istr(3)) ==> True\r\nistr(19).is_divisible_by(3) ==> False\r\nistr(19).is_divisible_by(istr(3)) == False\r\n```\r\nIt is also possible to test for divisibility of an ordinary int:\r\n```\r\nistr.is_divisible(18, 3) ==> True\r\nistr.is_divisible(19, 3) ==> False\r\n```\r\n#### test whether all characters are distinct\r\n\r\nWith the `all_distinct` method, it is possible to test whether all characters are distinct (i.e. no character appears more than once).\r\n\r\n```\r\nistr('01234').all_distict() ==> True\r\nistr('012340').all_distict() ==> False\r\nn98 = istr(98)\r\nn100 = n98 + 2\r\nistr(n98).all_distinct() ==> True\r\nistr(n100).all_distinct() ==> False\r\n```\r\n\r\n#### reverse an istr\r\n\r\nThe method `reversed()` will return an istr with the reversed content:\r\n```\r\nistr(456).reversed() ==> istr('654')\r\nistr('0456').reversed() ==> istr('6540')\r\n```\r\nThe same can -of course- be achieved with\r\n```\r\nistr(456)[::-1] ==> istr('654')\r\nistr('0456')[::-1] ==> istr('6540')\r\n```\r\n##### Note\r\n>\r\n> It is possible to reverse a negative istr, but the result can't be interpreted as an int anymore.\r\n>\r\n> ```\r\n> istr(-456).reversed() + 3 ==> TypeError\r\n> ```\r\n\r\n#### enumerate with istrs\r\n\r\nThe `istr.enumerate` class method can be used just as the built-in enumerate function.\r\nThe iteration counter however is an istr rather than an int. E.g. \r\n\r\n```\r\nfor i, c in istr.enumerate('abc'):\r\n print(f'{repr(i)} {c}')\r\n```\r\nprints\r\n```\r\nistr('0') a\r\nistr('1') b\r\nistr('2') c\r\n```\r\n#### itertools with istrs\r\nAll methods in itertools are also available directly from istr.\r\nNote that the result is istr-ed (apart from groupby and tee).\r\n\r\nThe following class methods are supported (provided their counterpart exists in the installed Python version's itertools):\r\n\r\n- istr.accumulate\r\n- istr.chain\r\n- istr.combinations\r\n- istr.combinations_with_replacement\r\n- istr.compress\r\n- istr.count\r\n- istr.cycle\r\n- istr.dropwhile\r\n- istr.filterfalse\r\n- istr.groupby (not istr-ed)\r\n- istr.islice\r\n- istr.pairwise\r\n- istr.permutations\r\n- istr.product\r\n- istr.repeat\r\n- istr.starmap\r\n- istr.takewhile\r\n- istr.tee (not istr-ed)\r\n- istr.zip_longest\r\n\r\nThis can be handy as these methods don't have to be imported from itertools anymore.\r\n\r\nAll methods have exactly the same (optional) parameters as their itertools counterpart.\r\n\r\nFor example:\r\n\r\n```\r\nlist(istr.repeat(1, 4)) ==> [istr('1'), istr('1'), istr('1'), istr('1')]\r\nnext(istr.count(3)) ==> istr('3')\r\n```\r\n\r\nOne more example:\r\n\r\n```\r\nfor t in istr.permutations(range(3)):\r\n print(t)\r\n```\r\nresults in\r\n```\r\n(istr('0'), istr('1'), istr('2'))\r\n(istr('0'), istr('2'), istr('1'))\r\n(istr('1'), istr('0'), istr('2'))\r\n(istr('1'), istr('2'), istr('0'))\r\n(istr('2'), istr('0'), istr('1'))\r\n(istr('2'), istr('1'), istr('0'))\r\n```\r\n\r\n#### concatenate an iterable\r\n\r\nThe `istr.concat` method can be useful to map all items of an iterable\r\nto `istr` and then concatenate these.\r\n\r\n`\r\n\r\n```\r\nlist(istr.concat(((1,2),(3,4))) ==> istr([12,34])\r\nlist(istr.concat(itertools.permutations(range(3),2))) ==> \r\n [istr('01'), istr('02'), istr('10'), istr('12'), istr('20'), istr('21')] \r\n```\r\n\r\n#### generate istr with digits\r\n\r\nThe class method `digits` can be used to return an istr of digits according to a given specification.\r\nThe method takes either no or a number of arguments.\r\n\r\nIf no arguments are given, the result will be `istr('0123456789')`.\r\n\r\nThe given argument(s) result in a range of digits.\r\n\r\n- `<n>` ==> n\r\n- `<n-m>` ==> n, n+1, ..., m\r\n- `-n>` ==> 0, 1, ... n\r\n- `n->` ==> n, n+1, ..., 9 if n is numeric (0-9), n, n+1, ... Z if n is a letter\r\n- `'-'` ==> 0, 1, ..., 9\r\n- `''` ==> 0, 1, ..., 9\r\n\r\n(n and m must be digits between 0 and 9 or letters letters between A and Z)\r\n\r\nWhen no stop value is specified, it will be\r\n\r\n* 9 if the start value is between 0 and 9\r\n* Z if the start value is between A and Z \r\n\r\nThe final result is an istr composed of the given range(s).\r\n\r\nHere are some examples:\r\n\r\n```\r\nistr.digits() ==> istr('0123456789')\r\nistr.digits('') ==> istr('0123456789')\r\nistr.digits('1') ==> istr('1')\r\nistr.digits('3-') ==> istr('3456789')\r\nistr.digits('-3') ==> istr('0123')\r\nistr('1-4', '6', '8-9') ==> istr('1234689')\r\nistr('1', '1-2', '1-3') ==> istr('11213')\r\nistr.digits('-z') ==> istr('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')\r\nistr.digits('A-F') ==> istr('ABCDEF')\r\nistr.digits('C') ==> istr('C')\r\nistr.digits('3-') ==> istr('34567879')\r\nistr.digits('X-') ==> istr('XYZ')\r\n```\r\n\r\n\r\n#### Subclassing istr\r\nWhen a class is derived from istr, all methods will return that newly derived class. \r\n\r\nE.g.\r\n```\r\nclass jstr(istr):\r\n ...\r\n \r\nprint(repr(jstr(4) * jstr(5)))\r\n```\r\nwill print `jstr('20')`\r\n\r\n#### Changing the way repr works\r\n\r\nIt is possible to control the way an `istr` instance will be repr'ed.\r\n\r\nBy default, `istr(5)` is represented as `istr('5')`.\r\n\r\nWith the `istr.repr_mode()` context manager, that can be changed:\r\n```\r\nwith istr.repr_mode('str'):\r\n five = istr(5)\r\n print(repr(five))\r\nwith istr.repr_mode('int'):\r\n five = istr(5)\r\n print(repr(five))\r\nwith istr.repr_mode('istr'):\r\n five = istr(5)\r\n print(repr(five))\r\n```\r\nThis will print\r\n```\r\n'5'\r\n5\r\nistr('5')\r\n```\r\nIf the repr_mode is `'int'` and the istr can't be interpreted as an int the string `?` will be returned:\r\n\r\n```\r\n with istr.repr_mode('int'):\r\n abc = istr('abc')\r\n print(repr(abc))\r\n```\r\n\r\nThis will print\r\n\r\n```\r\n?\r\n```\r\n\r\n##### Note\r\n>\r\n> The way an `istr` is represented is determined at initialization.\r\n\r\nIt is also possible to set the repr mode without a context manager:\r\n\r\n```\r\nistr.repr_mode('str')\r\nfive = istr('5')\r\nprint(repr(five))\r\n```\r\nThis will print\r\n```\r\n'5'\r\n```\r\nFinally, the current repr mode can be queried with `istr.repr_mode()`. So upon start:\r\n```\r\nprint(repr(istr.repr_mode()))\r\n```\r\nwill output `istr`.\r\n\r\n#### Changing the base system\r\n\r\nBy default, `istr` works in base 10. However it is possible to change the base system with the `istr.base()` context manager / method.\r\n\r\nAny base between 2 and 36 may be used.\r\n\r\nNote that the integer is **always** stored in base 10 mode, but the string\r\nrepresentation will reflect the chosen base (at time of initialization).\r\n\r\nSome examples:\r\n```\r\nwith istr.base(16):\r\n a = istr('7fff')\r\n print(int(a))\r\n\r\n b = istr(127)\r\n print(repr(b))\r\n```\r\nThis will result in\r\n```\r\n32767\r\nistr('7F')\r\n```\r\nAll calculations are done in the decimal 10 base system.\r\n\r\nNote that the way an `istr` is interpreted is determined at initialization.\r\n\r\nIt is also possible to set the repr mode without a context manager:\r\n```\r\nistr.base(16)\r\nprint(int(istr('7fff')))\r\n```\r\nThis will print\r\n```\r\n32767\r\n```\r\nFinally, the current base can be queried with `istr.base()`, so upon start:\r\n```\r\nprint(istr.base())\r\n```\r\nwill result in `10`.\r\n\r\n#### Changing the format of the string\r\n\r\nWhen an istr is initialized with a string the istr will be always stored as such.\r\n\r\n```\r\nrepr('4')) ==> istr('4')\r\nrepr(' 4')) ==> istr(' 4')\r\nrepr('4 ')) ==> istr('4 ')\r\n```\r\n\r\nFor initializing with an int (or other numeric) value, the string is by default simply the str representation\r\n\r\n```\r\nrepr(4)) ==> istr('4')\r\n```\r\n\r\nWith the `istr.int_format()` context manager this behavior can be changed.\r\nIf the format specifier is a number, most likely a single digit, that\r\nwill be the minimum number of characters in the string:\r\n\r\n```\r\nwith istr.int_format('3'):\r\n print(repr(istr(1)))\r\n print(repr(istr(12)))\r\n print(repr(istr(123)))\r\n print(repr(istr(1234)))\r\n```\r\nwill print\r\n```\r\nistr(' 1')\r\nistr(' 12')\r\nistr('123')\r\nistr('1234')\r\n```\r\nIf the string starts with a `0`, the string will be zero filled:\r\n```\r\nwith istr.int_format('03'):\r\n print(repr(istr(1)))\r\n print(repr(istr(12)))\r\n print(repr(istr(123)))\r\n print(repr(istr(1234)))\r\n```\r\nwill print\r\n```\r\nistr('001')\r\nistr('012')\r\nistr('123')\r\nistr('1234')\r\n```\r\n\r\n##### Note\r\n>\r\n> For bases other than 10, the string will never be reformatted!\r\n\r\n### Overview of operations\r\n\r\nThe table below shows whether the string or the int version of istr is applied.\r\n\r\n```\r\noperator/function int str Example\r\n-----------------------------------------------------------------------------------------\r\n+ x istr(20) + 3 ==> istr('23')\r\n_ x istr(20) - 3 ==> istr('17')\r\n* x istr(20) * 3 ==> istr('60')\r\n/ x istr(20) / 3 ==> istr('6')\r\n// x istr(20) // 3 ==> istr('6')\r\n% x istr(20) % 3 ==> istr('2')\r\ndivmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))\r\n** x istr(2) ** 3 ==> istr('8')\r\n<=, <, >, >= x istr('100') > istr('2') ==> True\r\nabs x abs(istr(-20)) ==> istr('20')\r\n== x x istr(20) == 20 ==> True | istr(20) == '20' ==> True\r\nbool x x *) bool(istr(' 0 ')) ==> False | istr('') ==> False\r\n@ x istr(20) @ 3 ==> istr('202020')\r\n| x istr(20) | '5' ==> istr('205')\r\nslicing x istr(12345)[1:3] ==> istr('23')\r\niterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]\r\nlen x len(istr(' 20 ')) ==> 4\r\ncount x istr(100).count('0') ==> 2\r\nindex x istr(' 100 ').index('0') ==> 2\r\nsplit x istr('1 2').split() ==> (istr('1'), istr('2'))\r\nstring format x f\"|{istr(1234):6}|\" ==> '|1234 |'\r\nother string methods x istr('aAbBcC').lower() ==> istr('aabbcc')\r\n istr('aAbBcC').islower() ==> False\r\n istr(' abc ').strip() ==> istr('abc')\r\n ...\r\n-----------------------------------------------------------------------------------------\r\n*) str is applied if is_int() is False\r\n\r\n```\r\n### Test script\r\nThere's an extensive pytest script in the `\\tests` directory.\r\n\r\nThis script also shows clearly the ways istr can be used, including several edge cases. Highly recommended to have a look at.\r\n\r\n\r\n\r\n### Badges\r\n  \r\n  \r\n\r\n",
"bugtrack_url": null,
"license": null,
"summary": "istr - strings you can count on",
"version": "1.0.12.post0",
"project_urls": {
"Homepage": "https://github.com/salabim/istr",
"Repository": "https://github.com/salabim/istr"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "251370c631cfcd6ab2179d0c687d3dd01bfe3dfa62767facc9255e3e14026da6",
"md5": "59e11a53eccf62b7192239fa6484f157",
"sha256": "30708e96d80e02b7e41f428af389bd50d0387c67c4468fbcddcefbf3eab97956"
},
"downloads": -1,
"filename": "istr_python-1.0.12.post0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "59e11a53eccf62b7192239fa6484f157",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 13999,
"upload_time": "2024-08-18T12:43:08",
"upload_time_iso_8601": "2024-08-18T12:43:08.205453Z",
"url": "https://files.pythonhosted.org/packages/25/13/70c631cfcd6ab2179d0c687d3dd01bfe3dfa62767facc9255e3e14026da6/istr_python-1.0.12.post0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7f5f7a087d543127ee10582ca5cc17215c7093ccf45fe5488d77b1164fe88aca",
"md5": "1288c3027c6d5057df9cab5c6b9c245d",
"sha256": "88383e1cc49766d45a2db3e5a6d5a5269dfbf11789633db2398b4174f03d5666"
},
"downloads": -1,
"filename": "istr_python-1.0.12.post0.tar.gz",
"has_sig": false,
"md5_digest": "1288c3027c6d5057df9cab5c6b9c245d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 24960,
"upload_time": "2024-08-18T12:43:09",
"upload_time_iso_8601": "2024-08-18T12:43:09.656889Z",
"url": "https://files.pythonhosted.org/packages/7f/5f/7a087d543127ee10582ca5cc17215c7093ccf45fe5488d77b1164fe88aca/istr_python-1.0.12.post0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-18 12:43:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "salabim",
"github_project": "istr",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "istr-python"
}