I am trying to figure out if my issue is a pycharm bug, or if I have not understood how to use property() correctly, or whether there is a more pythonic way to implement what I am trying to achieve. I do not have any formal programming training, so it's very possible I am just trying to go about this entirely wrong, and my searches haven't really clarified anything to me. I did look at this answer, which makes me think I am using property correctly, but in a much simpler situation, so I'm not sure if that still applies here. I recognize that there is quite a lot to this question, but it's how it all ties together which is causing me problems, so I don't know how to ask it in smaller more specific chunks.
General Aim: I have a class in which I want to make several properties that are all very similar, therefore I do not want to define each with an @property decorator.
In the code below, the # PROBLEM: ... is where PyCharm isn't recognising the property. This is what is making me unsure as to whether I am using property() correctly and is where my main question lies. Am I misusing property() somehow? Am I trying to do something fundamentally wrong (see below for more info on my intentions)? Or is it just a PyCharm bug, and this code is actually ok?
To further clarify my intentions overall intentions: I think in this example it looks like I should have A and B as subclasses of Test, but in my real code I don't want to clutter up A and B and they use very little from the Test instance. I mostly just want A, B, etc to be able check whether other properties exist, and very minimally use values from attributes of classes retrieved by those other properties. I am trying to keep my subclasses (A, B, etc) as easy to read/modify for someone who doesn't know much python as possible (working in a lab where I expect other students to modify only certain aspects of the code, and not have to understand the rest).
Here is the minimal(ish) example of what I am talking about:
# Parent Class which has lots of things relevant to A, B, etc
class PropClass:
def __init__(self, test_class):
self.test_class = test_class
# some init possibly using something from test_class
pass
# I want these subclasses to be as easy as possible to modify/write for non programmers
class A(PropClass):
# some additional methods etc (possibly using self.test_class)
pass
class B(PropClass):
# some additional methods etc (possibly using self.test_class)
pass
# I have many more of these
prop_dict = {
'a': A,
'b': B,
# Many more
}
class Test:
def prop(self, key):
"""Use this for 'prop' part of many different properties (only varying 'key')"""
private_key = '_'+key
if not getattr(self, private_key, None):
setattr(self, private_key, prop_dict.get(key)(self))
return getattr(self, private_key)
a = property(my_partial(prop, 'a', arg_start=1))
def test_method(self):
print(self.a) # PROBLEM: Pycharm highlights this and suggests creating a property for 'a', but I think it already exists
# I want these subclasses to be very easy to modify/create for non programmers
class SubTest(Test): # I want to be able to create subclasses with different combinations/additions of the possible properties I have
b = property(my_partial(Test.prop, 'b', arg_start=1))
def test_method(self):
print(self.a, self.b)
##################################
# Not really part of the question, but just including for completeness (basically partial() but skipping over 'self')
def my_partial(func, *args, arg_start=0, **kwargs):
"""Similar to functools.partial but with more control over which args are replaced"""
@functools.wraps(func)
def newfunc(*fargs, **fkwargs):
new_kwargs = {**kwargs, **fkwargs}
new_args = list(fargs[:arg_start]) # called args until fixed args at arg_start
new_args.extend(args) # Add fixed args
new_args.extend(fargs[arg_start + len(args) - 1:]) # Add any remaining called args
return func(*new_args, **new_kwargs)
# To make it more similar to functools.partial
newfunc.func = func
newfunc.args = args
newfunc.arg_start = arg_start # Might as well store this
newfunc.keywords = kwargs
return newfunc
##################################
Edit:
Pretty sure there is a bug in PyCharm because the warning highlighting shows up even with the minimal code below, but I am still unsure about whether I am going about things in a reasonable way in the above code.
class Test:
def func(self):
return 1
a_prop = property(func)
t = Test()
t.a_prop # <<< PyCharm suggests to make this a function call, but it is definitely a property.