Trouble Calling a Method in an Init

Trouble calling a method in an init

You cannot use self before all the stored properties have been initialised

The rule is simple and you are violating it here

self.date = getDateString()

infact this line is equivalente to

self.date = self.getDateString()

and as you can see you are using self while date has not been initialised yet.

You must init date before calling the instance method getDateString().

A class method

If you really want to call a method to initialize date it must be a class method

class SomeClass {

let title: String
let content: String
let date: String?

init(title: String, content: String) {

self.title = title
self.content = content
self.date = SomeClass.getDateString()

}

class func getDateString() -> String {
return "A date"
}
}

A few improvements

  1. If then date should contain... a Data then its type should be NSDate, not String
  2. If the date property should indicate the time when the value has been created then you can assign it = NSDate() on the declaration of the property
  3. created is a better name for this property

These 3 suggestions comes from the comment of user user3441734.

This is the updated code

class SomeClass {
let title: String
let content: String
let created = NSDate()

init(title: String, content: String) {
self.title = title
self.content = content
}
}

Calling a class function inside of __init__

Call the function in this way:

self.parse_file()

You also need to define your parse_file() function like this:

def parse_file(self):

The parse_file method has to be bound to an object upon calling it (because it's not a static method). This is done by calling the function on an instance of the object, in your case the instance is self.

Swift: why I can't call method from override init?

There are two competing initialization safety checks that are causing your problem.

Safety check 1


A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

and

Safety check 4


An initializer cannot call any instance methods, read the values of any instance properties, or refer to self as a value until after the first phase of initialization is complete.

Here is how it works.

override init() {
super.init() // Fails safety check 1: uuid is not initialized.
uuid = createUUID()
}

conversely,

override init() {
uuid = createUUID() // Fails safety check 4: cannot call an instance method before initialization is complete.
super.init()
}

Thanks to @Ruben in his answer

Is it possible to init a class and call a method at the same time?

To make the call like this, some_method must be static. That's because some_class is missing the braces () which would instantiate an object. Static methods do not have a self argument and have a @staticmethod attribute.

If that method shall return an instance, you need to call the constructor some_class().

class some_class:
def __init__(self, arg_1, arg_2):
self.arg_1 = arg_1
self.arg_2 = arg_2

@staticmethod
def some_method(arg_1, arg_2):
return some_class(arg_1, arg_2)

some_object = some_class.some_method('arg_1', 'arg_2')
print(some_object)

Style note: classes should be upper case in Python.

Why calling a function inside a Python class __init__ can be both Attribute and Method?

In case 1, your constructor calls fun() which has a line inside of it to overwrite itself with an attribute value. This is confusing and not a good thing to do because it is confusing.

In case 2, your fun method does not include the line to overwrite itself so it doesn't get overwritten.

In case 3, you never actually call your fun method so it never has a chance to overwrite itself. If you called it with person_1.fun() i.e. with parentheses, then it would execute and overwrite itself and from that point on, person_1.fun would be an attribute value.

Remember that in python, a function/method ONLY executes if it is called with parentheses. If you don't express it with parentheses, then the result of evaluation is not the output of the function, but instead the expression produces a reference to the function itself, which can be put in another variable or in a data structure and called later.

To illustrate this:

>>> def my_func():                                      
... print('got called')
... return 42
...
>>> x = my_func #no parentheses, x becomes an alias to my_func
>>> y = my_func() #parentheses means actually execute
got called
>>> y
42
>>> x
<function my_func at 0x765e8afdc0>
>>> x() #x is a reference to my_func and can be called itself
got called
42
>>>

How to call a function inside the __init__ function?

Here's the modified code:

class TemperatureFile:
def __init__(self, filename):
self.temperatureList = self.loadTemperatureData(filename) # The __init__requirement (this line). But it doesn't make sense to assign a method's return to a member, when that member could be easily set from within the method

def calculateAverage(self): # The calculateAverage requirement
if not self.temperatureList:
return None
#return sum(self.temperatureList) / len(self.temperatureList)
temp_sum = 0
for temp in self.temperatureList:
temp_sum += temp
return temp_sum / len(self.temperatureList)

def loadTemperatureData(self, filename): # The loadTemperatureData requirement (whole function)
temps = list()
with open(filename, "r") as temperartureFile:
for line in temperartureFile.readlines():
temps.append(float(line.strip()))
return temps

def main():
num1 = 35
num2 = 63
num3 = 40
temperatureFile = open("Temperatures.txt", "w")
temperatureFile.write(str(num1) + "\n")
temperatureFile.write(str(num2) + "\n")
temperatureFile.write(str(num3) + "\n")
temperatureFile.close()
Temperatures = TemperatureFile("Temperatures.txt")
print(Temperatures.calculateAverage())

main()

Notes:

  • I stripped a lot of the old (unused) code
  • The commented return line from calculateAverage is the simplified form of the 4 lines below it. You can decomment it and delete the 4 following lines
  • In main, instead of having num1, num2, ... you could create a list: temperatures = [35, 63, 40], and then iterate over it: for temperature in temperatures:, temperatureFile.write(str(temperature) + "\n"). It's more elegant, and if you want to add another temperature, you just add a new element in the list

Output:

(py35x64_test) c:\Work\Dev\StackOverflow\q47102727>"c:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" a.py
46.0

How do I call a classes method from another class without initialising the first class?

SOLUTION

Thanks all for your help, I have a better understanding of it now. What I did in the end as suggested in comments was to remove these particular methods from the classes and make them global functions. I actually went through and removed all methods that weren't specifically referencing self (or made sense to leave them as class methods) and made them global. Looking at it now I think this is a better way to structure the code.

Thanks all.

Calling a method from the init method?

Respectively (I'd use list formatting but I can't make it work with blockquotes...!):

Is this the correct way to set up the headers array in an init method?

Yes, but there's no point having the array variable, you might as well just do: headersArray = [[NSMutableArray alloc] init];

Am I allowed to call self.parentTableView from the init method?

No, to quote the Apple docs on Practical Memory Management:

Don’t Use Accessor Methods in Initializer Methods and dealloc

. You should access the ivar directly (as you do with headersArray)

Am I allowed to call a method from the init method (in this case, the prepareTags method calls self too. Will self be ready to use, even though the init method hasn't returned yet?

Yes. Just be very careful (your object may not have been fully initialised, it shouldn't use accessor methods so as to comply with the previous restriction, et cetera)

Is it bad form to call an instance method from within that instance's __init__ method?

It's fine to call instance methods within __init__, but be careful if they might be overridden in subclasses:

class A(object):

def __init__(self):
self.greet()

def greet(self):
print('Hello from A')

class B(A):

def __init__(self, name):
super(B, self).__init__()
self.name = name

def greet(self):
print('Hello from B', self.name)

Now if B is instantiated, B.greet is called by A.__init__ before its preconditions are satisfied (self.name is not defined).



Related Topics



Leave a reply



Submit