malfunc contains everyday functions customized for easier use, wrapped up neatly into a reusable library.
Project description
MalFunc Library 🛠️
A versatile Python utility library designed for robust data manipulation, numeric operations, and recursive structure traversal. Developed as a collaborative University Data Science project.
👥 The Development Team
| Member | GitHub Username | Core Responsibilities |
|---|---|---|
| Faizan Toheed | @faizantoheed456 | get_number(), get_sum(), get_indices() |
| Muhammad Usman | @dominator959 | get_mul(), vectorize_mul() |
| Shah Faisal Ilyas | @Faisalilyas17 | vectorize_sum(), get_unique_order_list() |
| Muhammad Rohan Jabbar | @mrj-005 | get_flat(), get_dtypes() |
🚀 Getting Started
Installation
Clone the repository to your local machine:
git clone https://github.com/dominator959/MalFunc.git
cd MalFunc
Basic Usage
import ops
import utils
# Securely get an integer from the user
age = ops.get_number("Enter your age:", to_int=True)
# Sum a nested list (ignoring non-numeric values)
result = ops.get_sum([1, [2, 3], "x", 4])
# => [5, 5] (inner [2,3]=5, outer [1,4]=5)
# Flatten a deeply nested list
flat = utils.get_flat([1, [2, [3, [4, 5]]]])
# => [1, 2, 3, 4, 5]
📚 Function Reference
Module: ops.py — Operations
get_number(prompt, to_int=False)
Repeatedly prompts the user until valid numeric input is provided. Eliminates the need for repetitive try-except blocks in calling code.
age = ops.get_number("Enter your age:", to_int=True) # returns int
price = ops.get_number("Enter price:") # returns float
| Parameter | Type | Description |
|---|---|---|
prompt |
str |
Message displayed to the user |
to_int |
bool |
If True, returns int; otherwise returns float (default: False) |
Returns: int or float
get_sum(data, results=None)
Recursively sums numeric items in a (possibly nested) list, ignoring non-numeric values. Returns a list of sums — one per nesting level encountered.
ops.get_sum([1, 2, 3]) # => [6]
ops.get_sum([1, "x", 2]) # => [3] ("x" ignored with notice)
ops.get_sum([1, [2, 3], 4]) # => [5, 5]
ops.get_sum([1, [2, [3, 4]]]) # => [7, 2, 1]
| Parameter | Type | Description |
|---|---|---|
data |
list |
Input list (may contain numbers, strings, or nested lists) |
results |
list |
Used internally for recursion; leave as None |
Returns: list of sums (innermost levels first)
get_mul(data)
Calculates the product of all numeric items in a (possibly nested) list. Non-numeric values are ignored. Returns a list of products — one per nesting level.
ops.get_mul([2, 3, 4]) # => [24]
ops.get_mul([2, "x", 3]) # => [6]
ops.get_mul([2, [3, 4]]) # => [12, 2]
ops.get_mul(["a", "b"]) # => [0] (no numeric items)
ops.get_mul([]) # => [0]
Returns: list of products (innermost levels first)
get_indices(data, current_path=None)
Recursively traverses a list and returns the exact positional path of every element, including those inside nested lists.
ops.get_indices(["a", "b"])
# => [{"path": [0], "value": "a"}, {"path": [1], "value": "b"}]
ops.get_indices([1, [2, 3]])
# => [
# {"path": [0], "value": 1},
# {"path": [1], "value": [2, 3]},
# {"path": [1, 0], "value": 2},
# {"path": [1, 1], "value": 3},
# ]
Returns: list of dict with keys "path" (index trail) and "value" (item)
vectorize_sum(a, b)
Performs element-wise addition of two lists of equal length. Supports nested lists recursively. Raises errors on mismatched lengths, types, or nesting structures.
ops.vectorize_sum([1, 2, 3], [4, 5, 6]) # => [5, 7, 9]
ops.vectorize_sum([1, [2, 3]], [10, [20, 30]]) # => [11, [22, 33]]
Raises: TypeError for non-list inputs, non-numeric elements, or mismatched nesting; ValueError for unequal lengths.
Module: utils.py — Utilities
vectorize_mul(a, b)
Performs element-wise multiplication of two lists of equal length. Supports nested lists recursively. Raises errors on mismatched lengths, types, or nesting structures.
utils.vectorize_mul([1, 2, 3], [4, 5, 6]) # => [4, 10, 18]
utils.vectorize_mul([2, [3, 4]], [10, [5, 5]]) # => [20, [15, 20]]
Raises: TypeError for non-list inputs, non-numeric elements, or mismatched nesting; ValueError for unequal lengths.
get_unique_order_list(data)
Removes duplicate items from a list while preserving the original order of first appearance — something a plain set() conversion cannot do.
utils.get_unique_order_list([3, 1, 3, 2, 1, 4]) # => [3, 1, 2, 4]
utils.get_unique_order_list(["b", "a", "b", "c", "a"]) # => ["b", "a", "c"]
Note: Items must be hashable (e.g., integers, strings, tuples).
Returns: list with duplicates removed, original order preserved.
get_flat(data)
Recursively flattens a deeply nested list into a single-level list, preserving element order and mixed types.
utils.get_flat([1, [2, 3], 4]) # => [1, 2, 3, 4]
utils.get_flat([1, [2, [3, [4, 5]], 6], 7]) # => [1, 2, 3, 4, 5, 6, 7]
utils.get_flat([1, ["a", [2.5, "b"]], None])# => [1, "a", 2.5, "b", None]
Returns: Flat list containing all elements in order.
get_dtypes(data)
Scans a collection and counts occurrences of each data type, useful for quick data profiling and cleaning.
utils.get_dtypes([1, "a", 2.5, "b", 3])
# => {"int": 2, "str": 2, "float": 1}
utils.get_dtypes([1, [2, 3], None, "x"])
# => {"int": 1, "list": 1, "NoneType": 1, "str": 1}
Returns: dict mapping type names (str) to their occurrence count (int).
🧪 Running Tests
All 9 functions have full unit test coverage in tests.py.
# Run all tests with verbose output
python -m unittest tests.py -v
# Or simply
python tests.py
Test coverage includes: valid inputs, edge cases (empty lists, no numeric items), error-raising conditions, and retry behaviour for get_number.
📝 Project Goals
- Robustness —
try-exceptblocks and type-checking prevent runtime crashes on bad input. - Recursion — Nested data structures are handled cleanly without depth limitations.
- Modularity — Logic is separated into two focused modules:
opsfor numeric operations andutilsfor structural utilities.
📜 License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file malfunc_faizantoheed456-0.2.0.tar.gz.
File metadata
- Download URL: malfunc_faizantoheed456-0.2.0.tar.gz
- Upload date:
- Size: 6.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f57e61b7a2a8abd4960c61c49f42b643323ea363805dc531c51ec1f65267575a
|
|
| MD5 |
78047a2b1981b8cea142e08433f6591c
|
|
| BLAKE2b-256 |
a561fe6b8d705cee2c12d3d8080323adbf62d4a2b846952f0e8ca59bbc64aaf5
|
File details
Details for the file malfunc_faizantoheed456-0.2.0-py3-none-any.whl.
File metadata
- Download URL: malfunc_faizantoheed456-0.2.0-py3-none-any.whl
- Upload date:
- Size: 7.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c8d078d9b9fa3cff013d4dfda7d58a68b1f86c21064d830ed222ee14e64e401
|
|
| MD5 |
7a65c7fa1f5b1b99dbda80f98b12779c
|
|
| BLAKE2b-256 |
b2007a4e287f868bb8a8dc050c4fafcad7fde1bf172a4232b13ee5ed8c3c2512
|