Property or method?

Make sure of course you use the set accessor in a scope that can see the protected set - i.e. in z_class implementation or in a derived class from it.

Hi @nathanletwory,

Could you please show me a small example what you mean?
set accessor in a scope ?

In your initial snippet it says

int[,,] some_name { get; protected set; }. With the class as you had you can’t do what @menno had on the last line of the accepted solution. There are two ways that specific setter can be used:

class a_class : z_class {
  void SomeFunc(int[,,] arr) {
    some_name = arr; // can access since we derive from z_class
  }

  int[,,] some_prop {
    get { return some_name; }
    set { some_name = value; } // ditto, can access, we derive
  }
}

// now can instantiate a_class, and use either some_prop or SomeFunc
// to set some_name
// we can _get_ some_name from outside the protected scope, but
// not set
z_instance = new z_class();
z_instane.some_name = new int[2,2,2]; // error, protected setter
a_instance = new a_class();
a_instance.some_prop = new int[2,2,2]; // ok, because setter is public
var arr = a_instance.some_name; // ok, because getter is public
a_instance.some_name = new int[2,2,2] // error, some_name setter still protected
2 Likes

Oh, yes. He actually mentiones it won’t work in a comment inside his previous reply.

I still do not understand how can I make a protected setter with python. I seem to be able to access both the property and the setter method from the instance.

class code:

# cPython3
class z():
    
    # Initializer
    def __init__(self):
        self.prop_1 = None
        self.prop_2 = 3
    
    @property
    def Prop1(self):
        return self.prop_1
    
    @Prop1.getter
    def Prop1(self):
        return self.prop_1
    
    @Prop1.setter
    def Prop1(self, val):
        self.prop_1 = val
    
    @property
    def Prop2(self):
        return self.prop_2
    
    @Prop2.getter
    def Prop2(self):
        return self.prop_2
    
    @Prop2.setter
    def Prop2(self,value):
        self.prop_2 = value


instance code:

#cPython3

from zClass import z


z_instance = z()

print(dir(z))
print("Before setting properties")
print("property 'prop_1' = {}".format(z_instance.prop_1))
print("property 'prop_2' = {}".format(z_instance.prop_2))

z_instance.Prop1 = 4513
z_instance.Prop2 = 213

print("After setting properties")
print("property 'prop_1' = {}".format(z_instance.prop_1))
print("property 'prop_2' = {}".format(z_instance.prop_2))

z_instance.prop_1 = 333
z_instance.prop_2 = 444

print("After setting properties")
print("property 'prop_1' = {}".format(z_instance.prop_1))
print("property 'prop_2' = {}".format(z_instance.prop_2))

I do not fully understand.

Python doesn’t do that kind of scoping. You can get at everything Python in anything Python. You cannot shield parts of classes from (mis)usage.

Not fiddling with ‘internals’ is solely up to the developer, and to the consumers of that code.

1 Like

I mean, one can (kinda sorta) do it using two leading underscores:

But yes, not for realz:

2 Likes

I always wondered why people use two underscores in object names, I thought it’s to avoid name conflicts between classes :man_facepalming:

Just as a clarification. A property in C# is kind of a mix of a class variable (field) and a method. It syntax sugar for getVariableX() and setVariableX(). You can do the same by implementing these two functions and a field variable. Using underscores you can simulate private/internal/protected access. Bytheway, you can also access private fields in C# by using reflection, so it shouldn’t be seen as a security feature, but rather as a don’t-do-this-dave hint.

2 Likes

I’m a little confused again.

class:

class z():
    
    # Initializer
    def __init__(self):
        self.prop_1 = None
        # making this property private by putting __ (double underscore) as prefix
        self.__prop_2 = 3
    
    @property
    def Prop1(self):
        return self.prop_1
    
    @Prop1.getter
    def Prop1(self):
        return self.prop_1
    
    @Prop1.setter
    def Prop1(self, val):
        self.prop_1 = val
    
    @property
    def Prop2(self):
        return self.__prop_2
    
    @Prop2.getter
    def Prop2(self):
        return self.__prop_2
    
    @Prop2.setter
    def Prop2(self,value):
        self.__prop_2 = value


instance implementation:

from zClass import z


z_instance = z()

#print(dir(z))
print("Before setting properties")
print("property 'prop_1' = {}".format(z_instance.prop_1))
print("property 'prop_2' = {}".format(z_instance.Prop2))

z_instance.Prop1 = 4513
z_instance.Prop2 = 213

print("After setting properties")
print("property 'prop_1' = {}".format(z_instance.prop_1))
print("property 'prop_2' = {}".format(z_instance.Prop2))

z_instance.prop_1 = 333
# ????
z_instance.__prop_2 = 444

print("After setting properties")
print("property 'prop_1' = {}".format(z_instance.prop_1))
print("property 'prop_2' = {}".format(z_instance.Prop2))

print(z_instance.__dict__)

output:

Why are _z__prop_2 and __prop_2 valuated differently?
Are they (it seems they are) different objects?

Could you please explain this with the dummies reference: Class Car: self.color = White - > porsche = Car() -> porsche.color = red

Because it appears now the porsche is both red and white :thinking:

hmm…does _z__prop_2 actually mean the default class property?..I’ll test

Nope…I’m still confused :roll_eyes:

I don‘t know if the concept of properties are very pythonic, because I see no benefit over writing two simple set and get functions directly, at least if you need to declare properties like this.

You may get a better understanding of all this when learning C#. What it looks like to me is, that very often you collide with C# concepts, which perfectly make sense in C# but are quite irrational in Python. This is also my problem with IronPython, because even for me, as being quite experienced with dotnet C# and CPython, I just get frustrated by mixing concepts in IronPython. It simply doesn’t work very well for both paradigms.
I think you really have a more simple life when using C#, being able to debug with visual studio. This also makes all your printing irrelevant, since a good debugger just tells you whats going on in every single line of code.( Rhino Python debugging is not bad either, just not as powerful)

1 Like

I believe, and maybe I’m wrong but anyways I try, by translating C# to Python I learn to understand C# better. Thus, learn to create C# code. The problem is there are still a lot of things I don’t know about Python (and programming in general). Trying to “hit two rabbits with a single bullet” (literal translation of a Bulgarian saying). I want to learn both C#, get better at Python and grok General Programming at the same time.

https://trello-attachments.s3.amazonaws.com/58e3f7c543422d7f3ad84f33/5d01751678f28538bd992907/c2f6bf103b9e2b862c2f3d14dd7056b1/Dwn-TyOWkAI5YAm.jpg

3 Likes

You can set truly protected instance attributes by using property with a getter but no setter in the class

# cpython3 

class C:
	def __init__(self):
		self._x = None

	@property
	def x(self):
		"""I'm the 'x' property."""
		return self._x

#	@x.setter
#	def x(self, value):
#		self._x = value

	@x.deleter
	def x(self):
		del self._x

c = C()
c.x = 3
Traceback (most recent call last):
File “”, line 1, in
AttributeError: can’t set attribute

1 Like

The advantage of property is that you can define additional logic with your get and set methods but users can access the attribute directly, if that makes more sense. For instance if you change the x location of a point as a user then you don’t have to know that in the background an index or log file is being updated. It gives the developer the option of defining the api separately from the implementation.

Yes but what is the true benefit in doing so? I would rather say it is a disadvantage if its not indicating if its a property or not. There is a reason you write properties with capital letter and variables with small letter in C#. It basically makes clear that properties may have additional behaviour attached. It should be clear that you access a property and not a field. Without this you may expecting different behaviour. Without a hint of being a property, it is even better to use setX(x) and getX() functions instead!
The true advantage in my oppinion is to shorten code, for a common pattern. But if you actually not having shorter code, then its pointless to implement it instead.
I mean in Python you need to define a decorator and 2 additional blocks for get and set, then what is the point in doing so? Restricting access to the variable with 2 underscores and writing a set and get method is shorter.
In C# this is very different …

Ahh you seem to be thinking like a developer :wink: - you want to understand the implementation! In my view, one use of OOP is to abstract the implementation away from the object model. As such, something which seems like an attribute can behave as an attribute even if the getter and setter are implemented as methods…

That potentially gives a more logical object model at the expense of some potentially unexpected hidden behaviour. The art of the api design is in elegantly reconciling the two… … probably using property as sparingly as possible:)

Of course the original PEP puts it far better than I could:

hmm :roll_eyes: is every class in fact a dictionary?

Every class has a __dict__ :

https://docs.python.org/2.7/library/stdtypes.html#object.dict

So I guess as long as the key is hashable, it is OK to use. But, by accessing __dict__ directly, you bypass the ‘write only-ness’ implemented in your override of __setattr__. As others have noted, I don’t think there is any real way to protect something in python.

In your example, I think you lost an indent on the else, but, if the purpose is to not allow foo.readonlyattr or foo.readonlyattr2 to be written to, and allow anything else, then:

class Foo:
    def __setattr__(self, name, val):
        if name == 'readonlyattr':
            raise TypeError('protected attribute "readonlyattr" cannot be written')
        elif name == 'readonlyattr2':
            raise TypeError('protected attribute "readonlyattr2" cannot be written')
        
        self.__dict__[name] = val
        

foo = Foo()
print foo.__dict__

try:
    foo.some_other_attribute = 'some_other_value'
except Exception as exp:
    print exp

print foo.__dict__

try:
    foo.readonlyattr = 'readonlyattr_value'
except Exception as exp:
    print exp

print foo.__dict__

try:
    foo.readonlyattr2 = 'readonlyattr2_value'
except Exception as exp:
    print exp
    
# Accessing __dict__ directly bypasses __setattr__

foo.__dict__['readonlyattr'] = 'bypassed'

print foo.__dict__

In your example’s else block, using “name” for the key should be just name, as you want the name variable passed in, not the string “name”. In the note, if you use str(name) then if the variable name has a __repr__ or __str__ method then I guess it would work, but I would just pass in the name variable directly and trust that dicts will be able to find a hash-able representation. If not you will get an exception, I think.