简体   繁体   中英

How to reinitialize a method within python class with updated object value

I want to have a class and be able to change an object value and have it flow through to methods and objects created in the class. In the below example I am trying have the new value 3 flow through but I keep getting the original value 2 . Am I doing it wrong?

class fun:
  g=2
  def a(c=g):
    return c
  z=g

fun.g = 3
fun.a()
fun.z

I have searched for __init__ functions but I don't see how they can help here. I tried created a new class making is the same as the fun class. That didn't work either.

as otheres mentioned, just want to point out that def a(c=g): the g has been replaced with 2 during class creation.

so after

fun.g = 3

print(fun.__dict__)
mappingproxy({'__module__': '__main__',
              'g': 3,
              'a': <function __main__.fun.a(c=2)>,
              'z': 2,
              '__dict__': <attribute '__dict__' of 'fun' objects>,
              '__weakref__': <attribute '__weakref__' of 'fun' objects>,
              '__doc__': None})

As you can see 'a': <function __main__.fun.a(c=2)>,

In python, methods and functions have their default values calculated and stored when the method or function is declared.

You can defer that calculation by doing it inside the method at runtime:

class fun:
  g=2
  def a(c=None):  # None is used here as a sentinal value
    if c is None:
        c=fun.g
    return c
  z=g

The problem is that parameters of a function is evaluated at compile time not runtime! Because in compile time the value of g is 2 and in your function you return that value, it's always going to be 2.

As a point, you call a() function on the class itself, so it's first parameter is not going to be filled with a reference to an instance. Story changes when you try to call it from instance of that class.

For demonstration take a look at this :

from datetime import datetime
from time import sleep

class C:
    def fn(self, date=datetime.now()):
        return date

obj = C()
print(obj.fn())
sleep(2)
print(obj.fn())

They both have same value.

The solution is to put g equal to None for default value and then inside the function check whether that value is passed or not:

from datetime import datetime
from time import sleep

class C:
    def fn(self, date=None):
        if date:
            return date
        return datetime.now()

obj = C()
print(obj.fn())
sleep(2)
print(obj.fn())

Not sure quite what you mean by reinitialize, __init__ occurs only on creation. If you create a new fun object it will be initialized in the same way with the same value.

$ cat fun.py

class fun(object):

    def __init__(self):
        self.g = 2

    def a(self, c=None):
        if c is None:
            c = self.g
        return c


first = fun()
second = fun()

first.g = 3

print(first.g)
print(first.a())
print(second.g)
print(second.a())
$ python3 fun.py
3
3
2
2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM