Skip to main content

Install

pip install class_property

Utilities

  • class_value - Hold a single value for a class and all instances.

  • class_property - Like a property, but works on MyClass.class_prop = value

  • metaclass - Create a metaclass that looks for class_value and class_property to register them.

  • decorate - Decorate a class to register any class_value and class_property.

A class must use the metaclass or decorate functions. Subclasses do not need to use decorate or metaclass. The metaclass is how the class object works with the descriptor.

Run

Class value usage.

Example:

from class_property import class_value

# doesn't matter if class_value.decorate, class_property.decorate, or decorate (same with metaclass)
class MyClass(object, metaclass=class_value.metaclass()):
    value = class_value(1)

mc = MyClass()
assert mc.value == 1
assert MyClass.value == 1

MyClass.value = 3
assert mc.value == 3
assert MyClass.value == 3

mc.value = 2
assert mc.value == 2
assert MyClass.value == 2


class SubClass(MyClass):
    hello = class_value("World")

sub = SubClass()
SubClass.hello = 'name'
assert sub.hello == 'name'
assert SubClass.hello == 'name'

sub.hello = 'John Doe'
assert sub.hello == 'John Doe'
assert SubClass.hello == 'John Doe'

sub.value = 7
assert SubClass.value == 7
assert sub.value == 7
assert mc.value == 7
assert MyClass.value == 7

Class property usage.

Example:

from class_property import class_value, class_property, decorate, metaclass

global GLOB
GLOB = 'Hello'

def get_glob():
    """Return the global GLOB value"""
    global GLOB
    return GLOB

def set_glob(value):
    global GLOB
    GLOB = value

# doesn't matter if class_value.decorate, class_property.decorate, or decorate (same with metaclass)
@decorate
class MyClass(object):
    _VALUE = None

    @class_property
    def value(self):
        return MyClass._VALUE

    @value.setter
    def value(self, value):
        MyClass._VALUE = value

    # Also works with no arguments
    @class_property
    def value2():
        return MyClass._VALUE

    @value2.setter
    def value2(value):
        MyClass._VALUE = value

    glob = class_property(get_glob, set_glob)

mc = MyClass()
assert mc.value is None
assert MyClass.value is None
MyClass.value = 3
assert mc.value == 3
assert MyClass.value == 3
mc.value = 2
assert mc.value == 2
assert MyClass.value == 2

assert mc.value2 == 2
assert MyClass.value2 == 2
mc.value2 = 5
assert mc.value == 5
assert MyClass.value == 5
assert mc.value2 == 5
assert MyClass.value2 == 5

assert MyClass.glob == 'Hello'
assert mc.glob == 'Hello'
MyClass.glob = 'Jack'
assert MyClass.glob == 'Jack'
assert mc.glob == 'Jack'
mc.glob = 'Jill'
assert MyClass.glob == 'Jill'
assert mc.glob == 'Jill'


class SubClass(MyClass):
    pass

sub = SubClass()
sub.glob = 'John'
assert SubClass.glob == 'John'
assert sub.glob == 'John'
assert MyClass.glob == 'John'
assert mc.glob == 'John'

Inheritance

After using decorate or metaclass to create the class using a metaclass class_value and class_property work as expected. When you inherit from a class_property class new class_value and class_property attributes work as expected as well. If you try to override a class_value or class_property things get complicated.

If you just want to change from class_value to a class_property set a new variable like normal. This will override the parent class attribute as well.

Example:

from class_property import class_value, class_property


class MyClass(object, metaclass=class_value.metaclass()):
    value = class_value(1)


class SubClass(MyClass):
    _VALUE = 2

    # This replaces "MyClass.value". class_value/class_property uses the metaclass, so we have to replace.
    # We can only change to a new object if we change the metaclass.
    @class_property
    def value(self):
        return SubClass._VALUE

    @value.setter
    def value(self, val):
        SubClass._VALUE = val


class SetValueClass(MyClass):
    value = 3


# Check that SetValueClass just changes the current value
assert MyClass.value == 3
assert SubClass.value == 3
assert SetValueClass.value == 3

mc = MyClass()
mc.value = 4

sub = SubClass()
sub.value = 7
assert sub.value == 7
assert SubClass.value == 7
assert SubClass._VALUE == 7

# MyClass.value is the new class_property from SubClass, because of the shared metaclass
assert mc.value == 7
assert MyClass.value == 7
assert SetValueClass.value == 7

If you want a disconnected new class_property then you need a new metaclass.

Example:

from class_property import class_property


class MyClass(object, metaclass=class_property.metaclass()):
    _VALUE1 = 1

    @class_property
    def value(self):
        return MyClass._VALUE1

    @value.setter
    def value(self, val):
        MyClass._VALUE1 = val


class SubClass(MyClass, metaclass=class_property.metaclass(MyClass)):
    _VALUE2 = 2

    # Because we have a different metaclass `SubClass.value` is different from `MyClass.value`
    @class_property
    def value():
        return SubClass._VALUE2

    @value.setter
    def value(val):
        SubClass._VALUE2 = val


mc = MyClass()
mc.value = 4

# SubClass.value is using a different metaclass and is disconnected from MyClass
sub = SubClass()
sub.value = 7
assert sub.value == 7
assert SubClass.value == 7
assert SubClass._VALUE2 == 7

# MyClass.value is using a different metaclass and is disconnected from SubClass
assert mc.value == 4
assert MyClass.value == 4
assert MyClass._VALUE1 == 4

Metadata

Release files for class-property 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for class-property 1.0.0
File Size Uploaded
class_property-1.0.0.tar.gz 8.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for class-property 1.0.0
File Interpreter ABI Platform
class_property-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.7 kB

Release files / class_property-1.0.0.tar.gz

Download URL class_property-1.0.0.tar.gz
Size 8.0 kB
Tags Source
SHA-256 checksum
How to use checksums
91860bde16ee5fbb8ee0f04d9d276e8dd229c7e866f4cd1e4d6d2a2b21d20d3a
BLAKE2b-256 checksum
How to use checksums
447233137436b56a1bbd0451d6ac219662545b9190c97d01a4e4768de4348e18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.6.8

Release files / class_property-1.0.0-py3-none-any.whl

Download URL class_property-1.0.0-py3-none-any.whl
Size 12.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
282a0ccf6ed14177f94b8013cd2e52db3b1443fd3317dab2e7876f08fa0ae6c0
BLAKE2b-256 checksum
How to use checksums
e72f393994379a3e979601f417d2f2d7ea95afcbcb5d837824d533d2e58d02ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.6.8

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page