Access base class attribute in derived class - in "class scope" - python-2.7

class Outer(object):
class InnerBase(object): _var = {'foo', 'bar'}
class Derived(InnerBase):
_var = _var | {'baz'} # NameError: name '_var' is not defined
_var = InnerBase._var | {'baz'} # name 'InnerBase' is not defined
_var = Outer.InnerBase._var | {'baz'} # free variable 'Outer'
# referenced before assignment in enclosing scope
Moving _var in Outer does not help - moving it in module scope would work but defeats the purpose of having classes. So how to go about that ?
EDIT: coming from Java so the scoping rules of classes are a head scratcher for me - a briefing would be appreciated. This works btw:
class Derived(InnerBase): pass
Derived._var = InnerBase._var | {'baz'}
but it's not the pinnacle of elegance.
Related: Nested classes' scope? - but here we specifically want to access our parent class (rather than the Outer type)
EDIT2: What I am actually after is a _var = __class__._var-like syntax (or hack), or an explanation as to why it's not there

Python never searches for a name in enclosing class statements. Mark Lutz uses the acronym LEGB to summarize scope in his introduction to Python (Learning Python): Python searches the local scope, then the local scope of any enclosing def statements, then the global scope, and finally the built-in scope. Class statements are excluded from this scope list; Python does not search enclosing class statements for a name.
One solution is to un-nest your classes. In Python, using un-nested classes is often preferred for its simplicity. But, of course, there are good reasons to nest classes as well. Why have you nested InnerBase? I wonder if you might have nested that class because of your experience in Java. Would the following work for you just as well?
class InnerBase(object):
_var = {'foo', 'bar'}
class Derived(InnerBase):
_var = InnerBase._var | {'baz'}
>>> Derived._var
set(['baz', 'foo', 'bar'])
The moment you nest these two class statements under another class statement they will be excluded from name searches, since they have become part of the larger class statement and are thus excluded from the searching of the various scopes.

You can bypass the class statement and use an explicit call to type.
class Outer(object):
class InnerBase(object): _var = {'foo', 'bar'}
Derived = type('Derived',
(InnerBase,),
{'_var': InnerBase._var | {'baz'}}
)
This works because Derived._var is not being set via an assignment statement in the class statement defining Derived, but is imported from a dictionary you create in the same environment as InnerBase itself.

When you put it in a method it works.
def __init__(self):
_var = Outer.InnerBase._var | {'baz'}
#_var = super(Outer.Derived, self)._var | {'baz'} # or with super
print(_var)
So my impression is that it's all about initialization.

Related

Why does class constructor get called for the second time after SUBMIT?

I have the following global class which is supposed to hold a reference to IF_OSQL_TEST_ENVIRONMENT as a static attribute.
CLASS zcl_static_holder DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-DATA sr_osql_test_environment TYPE REF TO if_osql_test_environment .
CLASS-METHODS class_constructor .
CLASS-METHODS set_osql_test_environment
IMPORTING
!ir_osql_test_environment TYPE REF TO if_osql_test_environment .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_static_holder IMPLEMENTATION.
METHOD class_constructor.
BREAK-POINT.
ENDMETHOD.
METHOD set_osql_test_environment.
sr_osql_test_environment = ir_osql_test_environment.
ENDMETHOD.
ENDCLASS.
Now I set this static attribute in a unit test in the following program. The class constructor of the above class gets called before the static attribute is initialised through the setter. However after sumbitting the report the class constructor is called for the second time and the static attribute of course is not set anymore.
REPORT zsubmit_with_static_holder.
CLASS lcl_test DEFINITION FINAL FOR TESTING
RISK LEVEL HARMLESS DURATION SHORT.
PUBLIC SECTION.
METHODS:
test FOR TESTING.
ENDCLASS.
CLASS lcl_test IMPLEMENTATION.
METHOD test.
DATA(lr_osql_test_environment) = cl_osql_test_environment=>create(
VALUE #( ( 'T100' ) )
).
zcl_static_holder=>set_osql_test_environment( lr_osql_test_environment ).
SUBMIT zsubmit_with_static_holder
AND RETURN.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
IF zcl_static_holder=>sr_osql_test_environment IS NOT BOUND.
WRITE / 'Not bound.'.
ENDIF.
SELECT COUNT( * ) FROM t100.
IF sy-subrc <> 0.
WRITE / 'No entries. Table mocked!'.
ENDIF.
Why is so? How can I get it to work? I found something about database LUWs and SAP LUWs and that it could be solved by shared memory object which on the other hand look very complex for such an easy usage in a unit test.
SUBMIT starts a new Internal Session and so all programs are loaded again.
Better move the code after start-of-selection in a class and call this class instead of using SUBMIT.
If you can't avoid SUBMIT, I think there's no solution, but who knows.

How do I access an object's eigenclass in Crystal?

In Ruby, it's possible to access the eigenclass (or "singleton class") of an object by reopening it. This is particularly useful for defining "private class methods":
class Foo
class << self
private
def declarative_method_name
end
end
declarative_method_name
end
# Foo.declarative_method_name => ERROR!
However, in Crystal this is not syntax:
Syntax error in ./test.cr:2: expecting token 'CONST', not '<<'
class << self
^
Is there another (or indeed any) way to achieve this in Crystal currently?
There's no eigenclass, or more commonly called singleton class in Ruby these days (given there's Object#singleton_class), in Crystal.
However defining class methods and calling them on the class level is supported:
class Foo
private def self.declarative_method_name
puts "hey"
end
declarative_method_name
end
https://carc.in/#/r/1316
The def self. construct here is specialized by the compiler and there's no more general concept beneath it, yet.
How would you make a super classes' new method private while still allowing it's subclasses' to be public?
class Foo
private self.new; end
end
class Bar < Foo
end
Bar.new #=> error: private method 'new' called for Foo:Class
It's also worth noting here that unlike in Ruby, class variables don't transcend inheritance. In Ruby the following code has a strange side effect...
class Foo
##var = 'foo'
def var
##var
end
end
class Bar < Foo
##var = 'bar'
end
puts Foo.new.var
It'll return 'bar' despite the fact that we modified the class variable on Bar. In crystal it returns 'foo' meaning that another reason we'd access the eiganclass, to store and read class level state safely, isn't necessary in crystal, we can just use class variables.

scope not working on Mongoid (undefined method `to_criteria')

I invoke ReleaseSchedule.next_release in other controller
and got the following error
NoMethodError (undefined method `to_criteria' for #<ReleaseSchedule:0x007f9cfafbfe70>):
app/controllers/weekly_query_controller.rb:15:in `next_release'
releae_schedule.rb
class ReleaseSchedule
scope :next_release, ->(){ ReleaseSchedule.where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at).first }
end
That's not really a scope at all, that's just a class method wrapped up to look like a scope. There are two problems:
You're saying ReleaseSchedule.where(...) so you can't chain the "scope" (i.e. ReleaseSchedule.where(...).next_release won't do what it is supposed to do).
Your "scope" ends in first so it won't return a query, it just returns a single instance.
2 is probably where your NoMethodError comes from.
If you really want it to be a scope for some reason then you'd say:
# No `first` or explicit class reference in here.
scope :next_release, -> { where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at) }
and use it as:
# The `first` goes here instead.
r = ReleaseSchedule.next_release.first
But really, you just want a class method:
def self.next_release
where(:release_date.gte => Time.now).without(:_id, :created_at, :updated_at).first
end
The scope macro is, after all, just a fancy way to build class methods. The only reason we have scope is to express an intent (i.e. to build queries piece by piece) and what you're doing doesn't match that intent.

Inspect Ember.js: Get the type of an object (Class)?

I use console.log() a lot, especially in combination with Ember.inspect(). But there's one thing I miss:
How can I find out the type of an object (Class)?
For example: Getting something like <Sandbox.ApplicationController:ember288> when inspecting Ember.get("controller")?
If you just want the model name (for example app/models/comment.js has the model name comment), you can use thing.constructor.modelName.
For example:
var aComment = this.get('store').createRecord('comment');
aComment.get('constructor.modelName') // => 'comment'
I understand you are looking for a string for debugging purposes, but I originally came to this question wanting to know specifically how to get the type of the object, not a string describing the object.
Using the built in Javascript property constructor will yield the class used to construct the instance. For example you could do:
person = App.Person.create();
person.constructor // returns App.Person
person.constructor.toString() // return "App.Person"
If you get Class, you can usually call toString() (or as a shortcut concat an empty string + '') to get something like <Sandbox.ApplicationController:ember288>
Another useful feature (in chrome) is the dir command.
dir(App.User)
This will give you the full object information, rather than just the name.
Be aware that some of these answers suggested here only work in development. Once your code is in production most of those methods / class names will get minified.
import Model from '#ember-data/model';
export default class Animal extends Model {
// ...
}
So in development:
const model = this.store.createRecord('animal');
model.constructor.name // returns Animal
in production:
const model = this.store.createRecord('animal');
model.constructor.name // returns 'i' (or any other single letter).
To avoid this, use constructor.toString()
const model = this.store.createRecord('animal');
model.constructor.toString() // returns 'model:animal'

Codeigniter always load in controller

I`m from Russia, so sorry for bad English.
I want to load template in every page in controller.
For example (library parser in autoload),
class Blog extends CI_Controller {
$header = array(
'header' => 'Welcome to my blog!'
);
$this->parser->parse('header', $header);
function index() {
...
echo "My text";
}
header.php:
<h1>{header}</h1>
<script>
alert("Welcome!");
</script>
But I get an PHP error:
syntax error, unexpected T_VARIABLE, expecting T_FUNCTION in line 6. Line 6:
$header = array(
How can I load header in every page? Thanks.
config.php:
$autoload['libraries'] = array('parser');
controller blog.php:
<?php
class Blog extends Controller {
function __construct()
{
parent::Controller();
$header = array('header' => 'Welcome to my blog!');
$this->parser->parse('header', $header);
}
function index()
{
echo "Мой текст";
}
}
?>
view header.php:
{header}
it works for me..
try calling the array with $this->header
Maybe it's a typing error but in the code from header.php you have typed {header} where I guess it should be {$header}
When loading class properties, like your $header above, php expects the property's visibility to be declared before the variable name. PHP5 has three visibility options: 'public', 'private', or 'protected'. I think this is why you are getting "unexpected T_VARIABLE". The difference between them are described at swik.net as:
To protect from accessibility pollution, PHP v5 introduces 3 prefixes for declaring class methods or variables: public, protected, and private.
Public methods and variables are accessible outside of the class. Protected are only accessible from inside of the class and inherited or parent classes. Private are only accessible from within the class itself.
try this: (I chose 'public' visibility, you can determine which is appropriate for your use)
public $header = array('header'=>'Welcome to my blog");
Next, I think you should call your parser in a constructor, rather than outside of a class method.
function _construct(){
parent::_construct();
$this->parser->parse('header',$this->header);
}
The constructor will be called every time the class is instantiated, loading your parser library method along with it.
Update:
Your comment suggests that the parser isn't working like you expect. I assume you have placed
$this->parser->parse('header,$this->header);
in the constructor function like I suggested. If that isn't working, create a function with the same name as your class and put the parser in there, that function will load every time the class is called, similar to the constructor, but let's see if that does the trick. I suggest taking the parser library out of auto load until you've resolved your problem, just to simplify things.
function blog(){
$this->load->library('parser');
$this->parser->parse('header',$this->header);
}