Why is it bad to use data types to initialize instances in Python? - class

Sorry if the answer to this is obvious, but I want to be sure, if you have(in Python):
class Name(object):
def __init__(self):
self.int_att1 = 0
self.int_att2 = 0
self.list_att = []
why can't(I know you can, but I've never seen a programmer do this) you initialize it in this way:
class Name(object):
def __init__(self):
self.int_att1 = int
self.int_att2 = int
self.list_att = list
Are there bad effects that come out of this?
What makes the former more Pythonic?
My best guess is because Python needs a value for instance.attribute. But if this is the case than why is it that using datatype works?

When you do self.int_att1 = int, the attribute int_att1 now references to the type int, I mean, is just another name for int. And I'll prove this in a simple way:
>>> number_type = int
>>> i = number_type()
>>> i
0
>>> type(i)
<type 'int'>
In this code, number_type becomes a "synonym" for the type int, that's why when I asked the type of i, it returned int and not number_type.
Same for self.list_att = list.
Probably, what you wanted to do was:
class Name(object):
def __init__(self):
self.int_att1 = int()
self.int_att2 = int()
self.list_att = list()
This is totally different, you are not longer assigning the type to the attribute. Instead, you are assigning the initial value of that type. Let's see what those initial values are:
>>> initial_int = int()
>>> initial_int
0
>>> initial_list = list()
>>> initial_list
[]
So, we can clearly see that the initial value of the type int is 0 and the initial value of the type list is [], and that is exactly what you were looking for!

You can, but it has a totally different effect. In the second case, you're setting the attribute equal to the value of the type, which is usually not what you want. In Python types are objects too, so this is legal.
It would let you do something like:
n = Name()
v = n.int_att1()
v would then be 0, because that's the value constructed by int's no-arg constructor.

From The Zen of Python: "Explicit is better than implicit."
You could certainly initialize with the default value of a type (not the type itself as in your example), but explicit is better than implicit. When you initialize with an actual value, there's no doubt about what you're getting.

Related

Equivalent of None in Scala

None is used to represent the absence of a value in Python.
For example, a node class for linked lists:
class Node:
def __init__(self, data=None, next_node=None):
self.data = data
self.next_node = next_node
Is there way to do this in Scala? I tried null but some sources advise against its usage.
class Node(new_data: Integer = null, new_next_node: Node = null) {
var data = new_data
var next_node = new_next_node
The same in Scala but Scala is typed, so a value that might be absent has to have the type Option[T]
case class Node(value: Option[Int] = None, node: Option[Node] = None)
In fact I also don't think use var is good practice in Scala. Perhaps you can define/initialize Node in the other way to avoid mutability.
But if you'd like to keep the code as much similar as the Python one, null is fine at least for new_next_node. And new_data can be initialized to some default value with type Int instead of using the boxed Integer; if new_data should be initialized by cases, it's better to use value: Option[Int] = None as #Sleiman Jneidi's answer has suggested.
Still, keep in mind that in Python, checking like if a is None is pythonic; however checking if a.isDefined against Option type is not quite scalaistic.

In Scala,Why is it not possible to change the value of var variable with different datatype

I am learning scala, trying to understand var variable .
Look at my below code
scala> var id =10
id: Int = 10
scala> id ="surender"
<console>:12: error: type mismatch;
found : String("surender")
required: Int
id ="surender"
var is mutable, that means we can change the value, While changing the value do we need to stick with same datatype?
Does it mean statically typed language?
Yes Scala is indeed a statically typed language. You can't reassign the data type at runtime.
The concept is called type safety and a lot people value it deeply. It is a matter of preference however.
You can specify the type when creating a var (or a val):
var id: Any = 10 // Don't actually do this!
id = "surender" // works
If you don't, the compiler infers the type from the initializer (in this case type of 10 is Int). However, Scala is indeed statically typed and there is very little you can usefully do with something of type Any. This is more useful e.g. in this situation:
var x: Option[Int] = None
x = Some(10) // doesn't compile without the signature above

Scala Theory / Basics: Variable not adding in function

If I can do this:
var num: Int = 1
num += 1
print(num)
Why can’t I do this? What would be the correct way? Fails on line 4
var num: Int = 1
def someFunction(num:Int){
num += 1
}
someFunction(num)
print(num)
Thanks for any insight. I've done some searching but nothing too helpful. I am mostly looking for the theory behind why this fails. I have accomplished what I need to with for statements but I am still wondering why this fails. Thanks!
It's a similar behavior to what you would see in Java. In Java and Scala you pass by value. A reference to your object/argument is copied and passed into the function. Thus, even if you would be able to change the value of that reference (num:Int) you would be working with a copy of that value - essentially a reassignment. Reassignment to arguments is allowed in Java by default but not in Scala. In other words there is nothing like C/C++ has where you can reference external variable and modify its value. That being said you can still achieve similar effect if the value you are trying to modify is an object field:
// I'm changing it directly but you could have a setter instead:
scala> class A(var m: Int)
defined class A
scala> val a = new A(0)
a: A = A#469c3554
scala> a.m
res0: Int = 0
scala> def someFunction(a: A, newVal: Int): Unit = { a.m = newVal }
someFunction: (a: A, newVal: Int)Unit
scala> someFunction(a, 3)
scala> a.m
res2: Int = 3
Using mutable state like this is NOT recommended. This example is just for illustration purposes. In this case you pass a copy of object reference a from which you can access the field directly and modify it.
If you want to understand this better read up on passing by value and passing by reference. Contrast C/C++ pointer and by reference args with Java and Scala. One difference between Scala and Java here is that in Java everything is a var by default, so if you write your arg as final num in Java it will also fail compilation and will work similarly to Scala in this case.
Because the JVM uses call-by-value semantics, and because Int is a primitive type (not an object reference).
What this means is that num inside the method is not the same as num on the outside, the only thing passed to the method is 1
It's a good thing too... It's bad enough when you have a mutable object and some innocent-looking method goes and changes things around behind your back. I don't wish to imagine the new category of bugs that would emerge if the same risk also existed for simple numbers!
#flavian's link answers the "why not" part, but here's how you do what you're trying to do. Make someFunction a function instead of a procedure.
var num = 1
def someFunction(num: Int) = num + 1
num = someFunction(num)
Note though that this isn't idiomatic scala. Avoid using vars whenever you can for best style.
Or alternatively for even worse style (seriously, this works, but don't ever do it):
var num = 1
def someFunction() = num += 1
someFunction()
print(num)

Scala - mapping a list of integers to a method that receives java.lang.Object

Working in Scala-IDE, I have a Java library, in which one of the methods receives java.lang.Object. And I want to map a list of Int values to it. The only solution that works is:
val listOfInts = groupOfObjects.map(_.getNeededInt)
for(int <- listOfInts) libraryObject.libraryMethod(int)
while the following one:
groupOfObjects.map(_.getNeededInt).map(libraryMethod(_)
and even
val listOfInts = groupOfObjects.map(_.getNeededInt)
val result = listOfInts.map(libraryObject.libraryMethod(_))
say
type mismatch; found : Int required: java.lang.Object Note: an
implicit exists from scala.Int => java.lang.Integer, but methods
inherited from Object are rendered ambiguous. This is to avoid a
blanket implicit which would convert any scala.Int to any AnyRef. You
may wish to use a type ascription: x: java.lang.Integer.
and something like
val result = listOfInts.map(libraryObject.libraryMethod(x => x.toInt))
or
val result = listOfInts.map(libraryObject.libraryMethod(_.toInt))
does not work also.
1) Why is it happening? As far as I know, the for and map routines do not differ that much!
2) Also: what means You may wish to use a type ascription: x: java.lang.Integer? How would I do that? I tried designating the type explicitly, like x: Int => x.toInt, but that is too erroneus. So what is the "type ascription"?
UPDATE:
The solution proposed by T.Grottker, adds to it. The error that I am getting with it is this:
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf[java.lang.Object])
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf{#null#}[java.lang.Object]{#null#}) {#null#}
and I'm like, OMG, it just grows! Who can explain what all these <null> things mean here? I just want to know the truth. (NOTE: I had to replace <> brakets with # because the SO engine cut out the whole thing then, so use your imagination to replace them back).
The type mismatch tells you exactly the problem: you can convert to java.lang.Integer but not to java.lang.Object. So tell it you want to ask for an Integer somewhere along the way. For example:
groupOfObjects.map(_.getNeededInt: java.lang.Integer).map(libraryObject.libraryMethod(_))
(The notation value: Type--when used outside of the declaration of a val or var or parameter method--means to view value as that type, if possible; value either needs to be a subclass of Type, or there needs to be an implicit conversion that can convert value into something of the appropriate type.)

Unexpected Scala default values behavior

Why do the default values here behave differently when assigned explicitly to a val, versus printed directly?
package blevins.example
class SimpleWrap[T] {
var t: T = _
def get = t
}
object App extends Application {
val swb = new SimpleWrap[Boolean]
val b = swb.get
println("b: " + b) // b: false
println("swb.get: " + swb.get) // swb.get: null
val swi = new SimpleWrap[Int]
val i = swi.get
println("i: " + i) // i: 0
println("swi.get: " + swi.get) // swi.get: null
}
I'm using 2.8r19890.
Edit - It seems the strangeness happens when "get" is called expecting an Any.
val any1: Any = swb.get
val any2: Any = b
println("any1: " + any1) // any1: null
println("any2: " + any2) // any2: false
I'm pretty sure that this is something to do with boxing/unboxing of the primitives. If you write generic code to work on primitives, you have to box the primitive and then unbox it at the place you've used it as a primitive. I am not sure what unboxing algorithm is used, but I suppose it is along the following lines:
if(box == null)
default value
else
box.unbox
Therefore, very strangely I might add, the default value of the field t in your simple wrapper class is always going to be null, as the field is always going to be a boxed primitive, as generics are implemented at the JVM level by type erasure. Therefore, all the JVM sees is that t is of type Object, with a value of null. The method get will therefore always return null, but when the generic method get is supposed to return a primitive type, the null gets unboxed to the default value.
Also, a bit of poking around with reflection does indeed show that the field is indeed null.
val sw = new SimpleWrap[Boolean]
sw.getClass.getDeclaredFields.map {
f => f.setAccessible(true)
f.get(sw)
}
Oh the fun of nulls. One solution to this problem would be to use the 2.8 #specialised annotation, if that has been implemented in the nightly build you use.
Or, even better, the Scala compiler could default those fields to boxed defaults of the actual defaults of the primitives used. For example, in the case of a SimpleWrap[Boolean], t would have the type Object and the value java.lang.Boolean(false) at runtime.
EDIT: Bug report submitted.
Another weird thing:
val x: Int = null.asInstanceOf[Int] // 0
val y: Boolean = null.asInstanceOf[Boolean] // false
This is something that should be solved in order for generics to really be generic, and have consistent behaviour! At the moment your get method doesn't have a consistent behaviour.
-- Flaviu Cipcigan