class Account
def initialize(starting_balance = 0)
#balance = starting_balance
end
def balance #instance getter method
#balance #instance variable visible only to this object
end
def balance=(new_amount)
#balance = new_amount
end
def deposit(amount)
#balance+=amount
end
##bank_name= "MyBank.com" # class (static) variable
# A class method
def self.bank_name
##bank_name
end
# or: def SavingsAccount.bank_name : ##bank_name : end
end
I want to understand the code snippets in bold. What do they do? what is the difference between a setter and initialize method.
If I had an object test=Account.new() and why is test(30) giving an error. Isn't that suppose to call the setter method with parameter 30 and set the balance?
initialize is the method that is called on the newly created object when you do Account.new or Account.new(my_starting_balance). In the first case initialize would be called with the default value 0 for starting_balance and in the second with my_starting_balance.
The setter method balance= is called when you do my_account.balance = some_value where my_account is an instance of the class Account. So if you have the following code, initialize will be called on line 1 (with 0 as its argument) and balance= on line 2 (with 23) as its argument:
my_account = Account.new
my_account.balance = 23
Of course in this case I could just as well write the following and not use the setter method at all:
my_account = Account.new(23)
However that doesn't always work because some times you might want to change the value of balance after the object has already been created.
If I had an object test=Account.new() and why is test(30) giving an error.
Because test(30) means "call the method test with the argument 30" and there is no method called test in your code.
Regarding the second bolded part of your code: As the comments indicate, it sets a class variable named ##bank_name and defines a class method that returns that variable's value.
Related
I have a custom DAG (meant to be subclassed), let's name it MyDAG. In the __enter__ method I want to add (or not) an operator based on the subclassing DAG. I'm not interested in using the BranchPythonOperator.
class MyDAG(DAG):
def __enter__(self, context):
start = DummyOperator(taks_id=start)
end = DummyOperator(task_id=end)
op = self.get_additional_operator()
if op:
start >> op
else:
start >> end
retrun self
def get_additional_operator(self):
# None if the subclass doesn't add any operator. A reference to another operator otherwise
if get_additional_operator is returning a reference, I'm obtaining this shape (two branches):
* start --> op
* end
otherwise, if it's returning None, I'm obtaining this (one branch):
* start --> end
What I want is not having end at all in the subclass inherting from MyDAG if get_additional_operator doesn't return None, something like this:
* start --> op
Instead of the two branches I'm obtaining above.
Airflow is somehow parsing every operator declared in the __enter__ method of a subclass of MyDAG. From that assumption, in order not to have an operator it only suffices to declare the operator in the right place. code below:
class MyDAG(DAG):
def __enter__(self, context):
start = DummyOperator(taks_id=start)
op = self.get_additional_operator()
if op:
start >> op
else:
end = DummyOperator(task_id=end)
start >> end
retrun self
def get_additional_operator(self):
# None if the subclass doesn't add any operator. A reference to another operator otherwise
The declaration of the end operator is made in the else section. I think it's only parsed when the else is evaluated to true.
How to check that a type implements an interface in Julia?
For exemple iteration interface is implemented by the functions start, next, done.
I need is to have a specialization of a function depending on wether the argument type implements a given interface or not.
EDIT
Here is an example of what I would like to do.
Consider the following code:
a = [7,8,9]
f = 1.0
s = Set()
push!(s,30)
push!(s,40)
function getsummary(obj)
println("Object of type ", typeof(obj))
end
function getsummary{T<:AbstractArray}(obj::T)
println("Iterable Object starting with ", next(obj, start(obj))[1])
end
getsummary(a)
getsummary(f)
getsummary(s)
The output is:
Iterable Object starting with 7
Object of type Float64
Object of type Set{Any}
Which is what we would expect since Set is not an AbstractArray. But clearly my second method only requires the type T to implement the iteration interface.
my issue isn't only related to the iteration interface but to all interfaces defined by a set of functions.
EDIT-2
I think my question is related to
https://github.com/JuliaLang/julia/issues/5
Since we could have imagined something like T<:Iterable
Typically, this is done with traits. See Traits.jl for one implementation; a similar approach is used in Base to dispatch on Base.iteratorsize, Base.linearindexing, etc. For instance, this is how Base implements collect using the iteratorsize trait:
"""
collect(element_type, collection)
Return an `Array` with the given element type of all items in a collection or iterable.
The result has the same shape and number of dimensions as `collection`.
"""
collect{T}(::Type{T}, itr) = _collect(T, itr, iteratorsize(itr))
_collect{T}(::Type{T}, itr, isz::HasLength) = copy!(Array{T,1}(Int(length(itr)::Integer)), itr)
_collect{T}(::Type{T}, itr, isz::HasShape) = copy!(similar(Array{T}, indices(itr)), itr)
function _collect{T}(::Type{T}, itr, isz::SizeUnknown)
a = Array{T,1}(0)
for x in itr
push!(a,x)
end
return a
end
See also Mauro Werder's talk on traits.
I would define a iterability(::T) trait as follows:
immutable Iterable end
immutable NotIterable end
iterability(T) =
if method_exists(length, (T,)) || !isa(Base.iteratorsize(T), Base.HasLength)
Iterable()
else
NotIterable()
end
which seems to work:
julia> iterability(Set)
Iterable()
julia> iterability(Number)
Iterable()
julia> iterability(Symbol)
NotIterable()
you can check whether a type implements an interface via methodswith as follows:
foo(a_type::Type, an_interface::Symbol) = an_interface ∈ [i.name for i in methodswith(a_type, true)]
julia> foo(EachLine, :done)
true
but I don't quite understand the dynamic dispatch approach you mentioned in the comment, what does the generic function looks like? what's the input & output of the function? I guess you want something like this?
function foo(a_type::Type, an_interface::Symbol)
# assume bar baz are predefined
if an_interface ∈ [i.name for i in methodswith(a_type, true)]
# call function bar
else
# call function baz
end
end
or some metaprogramming stuff to generate those functions respectively at compile time?
I'm using pytest.mark to give my tests kwargs. However, if I use the same mark on both the class and a test within the class, the class's mark overrides the mark on the function when the same kwargs are used for both.
import pytest
animal = pytest.mark.animal
#animal(species='croc') # Mark the class with a kwarg
class TestClass(object):
#animal(species='hippo') # Mark the function with new kwarg
def test_function(self):
pass
#pytest.fixture(autouse=True) # Use a fixture to inspect my function
def animal_inspector(request):
print request.function.animal.kwargs # Show how the function object got marked
# prints {'species': 'croc'} but the function was marked with 'hippo'
Where'd my hippo go and how can I get him back?
There are unfortunately various pytest bugs related to this, I'm guessing you're running into one of them. The ones I found are related to subclassing which you don't do there though.
So I've been digging around in the pytest code and figured out why this is happening. The marks on the functions are applied to the function at import time but the class and module level marks don't get applied on the function level until test collection. Function marks happen first and add their kwargs to the function. Then class marks overwrite any same kwargs and module marks further overwrite any matching kwargs.
My solution was to simply create my own modified MarkDecorator that filters kwargs before they are added to the marks. Basically, whatever kwarg values get set first (which seems to always be by a function decorator) will always be the value on the mark. Ideally I think this functionality should be added in the MarkInfo class but since my code wasn't creating instances of that I went with what I was creating instances of: MarkDecorator. Note that I only change two lines from the source code (the bits about keys_to_add).
from _pytest.mark import istestfunc, MarkInfo
import inspect
class TestMarker(object): # Modified MarkDecorator class
def __init__(self, name, args=None, kwargs=None):
self.name = name
self.args = args or ()
self.kwargs = kwargs or {}
#property
def markname(self):
return self.name # for backward-compat (2.4.1 had this attr)
def __repr__(self):
d = self.__dict__.copy()
name = d.pop('name')
return "<MarkDecorator %r %r>" % (name, d)
def __call__(self, *args, **kwargs):
""" if passed a single callable argument: decorate it with mark info.
otherwise add *args/**kwargs in-place to mark information. """
if args and not kwargs:
func = args[0]
is_class = inspect.isclass(func)
if len(args) == 1 and (istestfunc(func) or is_class):
if is_class:
if hasattr(func, 'pytestmark'):
mark_list = func.pytestmark
if not isinstance(mark_list, list):
mark_list = [mark_list]
mark_list = mark_list + [self]
func.pytestmark = mark_list
else:
func.pytestmark = [self]
else:
holder = getattr(func, self.name, None)
if holder is None:
holder = MarkInfo(
self.name, self.args, self.kwargs
)
setattr(func, self.name, holder)
else:
# Don't set kwargs that already exist on the mark
keys_to_add = {key: value for key, value in self.kwargs.items() if key not in holder.kwargs}
holder.add(self.args, keys_to_add)
return func
kw = self.kwargs.copy()
kw.update(kwargs)
args = self.args + args
return self.__class__(self.name, args=args, kwargs=kw)
# Create my Mark instance. Note my modified mark class must be imported to be used
animal = TestMarker(name='animal')
# Apply it to class and function
#animal(species='croc') # Mark the class with a kwarg
class TestClass(object):
#animal(species='hippo') # Mark the function with new kwarg
def test_function(self):
pass
# Now prints {'species': 'hippo'} Yay!
struct MyData
data
# constructor
function MyData()
data = 1
end
end
myData = MyData()
myData.data #error
I assumed Julia's struct was just like struct in C. So I don't know why I get an error there:
type int64 has no field data
Functions in Julia return the last expression in them. In this case, it is data = 1, that is data is returned instead of new instance of MyData. Simply add line with new(data) after data = 1 to return new instance of MyData, and it will work properly.
Normally you want to use a so-called "outer constructor", i.e. a function of the same name that is defined outside the definition of the type itself. You also want to specify the type of each field as a concrete type, e.g. Int in this example:
struct MyType
data::Int
end
This has already defined, automatically, a couple of constructors:
x = MyType(3)
x.data
You can define new outer constructors, e.g. to have a default value:
MyType() = MyType(0) # defines a new constructor
x = MyType()
The kind of constructor you were trying to define is called an "inner constructor" (since it lives inside the type definition). It is used when there is something special that you want to force for each new object. For example, you could make sure that the data must be positive and throw and error if not:
struct MyType2
data::Int
function MyType2(x::Int)
if x <= 0
throw(ArgumentError("x must be positive"))
end
new(x)
end
end
x = MyType2(3)
y = MyType2(-17)
You should have a look at the documentation on constructors:
http://docs.julialang.org/en/release-0.4/manual/constructors/
My question is how can I overload certain method within a certain class in Julia?
In other words suppose I have a following definition of a class:
type Sometype
prop::String
setValue::Function
# constructor
function Sometype()
this = new ()
this.prop = ""
####### v1 #######
this.setValue = function(v::Real)
println("Scalar Version was Invoked!")
# operations on scalar...
# ...
end
####### v2 #######
this.setValue = function(v::Vector{Real})
println("Vector Version was Invoked!")
# operations on vector...
# ...
end
####### v3 #######
this.setValue = function(v::Matrix{Real})
println("Matrix Version was Invoked!")
# operations on Matrix...
# ...
end
return this
end
end
So when I say in my main code:
st = Sometype()
st.setValue(val)
depending on whether val is a scalar, vector or matrix it would invoke the corresponding version of a setvalue method. Right now, with definition above, it overrides definitions of setvalue with the last one (matrix version in this case).
This style of Object-Oriented Programming (OOP), in which the functions live inside objects, is not used in Julia.
Instead, in Julia we just define methods outside the object definition. E.g.:
type Sometype
prop::String
end
Sometype(v::Real) = ...
function Sometype{T}(v::Vector{T}) # parametric type
....
end
Note that the first definition is an example of the short-hand way of defining simple functions on a single line, and the second example is for more complicated functions.
As pointed out by #GnimucKey, instead of v::Vector{Real}, you should use v::Vector{T} with the function parametrised by T. I have changed my answer accordingly. An argument specified as v::Vector{Real} will never match an argument, since it is impossible to create objects of the abstract type Real, and the invariance of types means that an object like Vector{Float64} is not a subtype of Vector{Real}.