When I used a double splat for a method, I'm not allowed to define a variable with a type within the method:
def show(**attrs)
place : String = "w"
puts place
end
show(name: "Bobby") # This works.
show(name: "Bobby", place: "World") # This fails:
#
#in tmp.cr:2: variable 'place' already declared
#
# place : String = "w"
# ^~~~~
Is this the expected behaviour when using double splats? I couldn't find anything in the Crystal Book about this: https://crystal-lang.org/docs/syntax_and_semantics/splats_and_tuples.html
This is a bug, please report it as such.
Note that declaring local variables with a type is not a recommended practice. Because it was a recent addition, it is not well tested and apparently prone to bugs.
You can see that this works, anyway:
def show(**attrs)
place = "w"
puts place
puts attrs[:place]
end
show(name: "Bobby", place: "World")
w
World
Related
In Theory: When game_start is called and the user inputs 'easy' the variable quiz_paragraph should assume the value of easy_paragprah
In Actuality: The value of quiz_paragraph is set to "
I can verify that user_difficulty is being set properly and is feeding 'easy' properly into set_difficulty. The if statement runs but doesn't alter the value of quiz_paragraph.
Can anyone tell me what I am missing here?
# Easy Paragraph
easy_paragraph = '''\n___1___ is a programming ___2___ used to solve simple and complex problems. ___1___ like
many languages can be used to display a message to a user using ___3___. Try it sometime.
To display this common message by typing ___3___ '___4___ World!' \n'''
# Init Variables
user_difficulty = ""
quiz_paragraph = ""
# Ask user difficulty
def ask_difficulty():
user_difficulty = raw_input("What difficulty level would you like? ")
return user_difficulty
# Difficulty sets returned Paragraph
def set_difficulty(difficulty):
if difficulty == "easy":
quiz_paragraph = easy_paragraph
return quiz_paragraph
else:
print '''Sorry, that is not a valid choice.'''
# Start the game
def game_start():
set_difficulty(ask_difficulty())
print quiz_paragraph
# Game Start Test
game_start()
It looks like you have an issue with scope.
The quiz_paragraph variable within set_difficulty, is not the same as the 'global' quiz_paragraph. Although they currently share the same name, you could rename the one inside set_difficulty to foo and you would have the same result.
You need to set the 'global' quiz_paragraph to the value returned by set_difficulty, or a better another local variable within game_start. That is,
def game_start():
quiz_paragraph = set_difficulty(ask_difficulty())
print quiz_paragraph
or
def game_start():
my_difficulty = set_difficulty(ask_difficulty())
print my_difficulty
I was recently trying to solve a challenge on Hackerrank which asked us to figure out whether a string containing brackets (e.g. {}, (), and [] ) was balanced or not (source: https://www.hackerrank.com/challenges/balanced-brackets). I wanted to solve this using the following approach that also integrated the initial format Hackerrank provided:
import sys
def isBalanced(s):
#insert code here
if __name__ == "__main__":
t = int(raw_input().strip())
for a0 in xrange(t):
s = raw_input().strip()
result = isBalanced(s)
print result
I should also note that site has configured the following as being the standard input in order to test the functionality of the code:
3
{[()]}
{[(])}
{{[[(())]]}}
In order to get the following output:
YES
NO
YES
However, I didn't understand how to approach this code, chiefly because I did not understand why Hackerrank used the if __name__ == "__main__": clause, as I thought that this clause was only used if someone wanted their module to be executed directly rather than executed through being imported in another script (source: What does if __name__ == "__main__": do?). I also did not understand the for loop containing for a0 in xrange(t): since a0 is not used within the for loop for anything, so I'm really unsure how the standard input would be processed.
So I ended up looking up the solution on the discussion page, and here it is below:
lefts = '{[('
rights = '}])'
closes = { a:b for a,b in zip(rights,lefts)}
def valid(s):
stack = []
for c in s:
if c in lefts:
stack.append(c)
elif c in rights:
if not stack or stack.pop() != closes[c]:
return False
return not stack # stack must be empty at the end
t = int(raw_input().strip())
for a0 in xrange(t):
s = raw_input().strip()
if valid(s):
print 'YES'
else:
print 'NO'
This code also confuses me, as the writer claimed to utilize a data structure known as a "stack" (although it seems to be just a Python list to me). And although the writer removed the if __name__ == "__main__": statement, they retained the for a0 in xrange(t):, which I'm not sure how it processes the standard input's integer and corresponding strings.
Furthermore, although the isBalanced function confuses me because it returns not stack. In a hash comment on the return statement of the function, the writer also states the # stack must be empty at the end. What does that mean? And how could this list be empty if, during the clause if c in lefts:, the stack is appended with the character of the string that is being iterated in the for-loop. So why would the function return not stack? Wouldn't it be consistent to return True so that the function would act as a Boolean tester (i.e. would return true if a certain object adhered to certain criteria, and false if the the object did not)?
I am still relatively new to coding so there are a lot of principles I am not familiar with. Can anyone illuminate as to how this would work?
iam not sure how your code works .. if name == "main": do?). just exlained where you use of Before executing the code, it will define a few special variables. For example, if the python interpreter is running that module (the source file) as the main program, it sets the special name variable to have a value "main". If this file is being imported from another module, name will be set to the module's name
I am trying to use ConfigParser in the following situation. I am running some code after which i have an object with several attributes. I pick out some of these attributes and write them to a .ini file with configparser. This works fine and my .ini file looks something like this.
[Section]
path = "D:\\"
number = 10.0
boolean = False
Then with some other script I want to read the file and add the items as attributes to another object (self) using.
parser.read('file.ini')
self.__dict__.update(dict(parser.items("Section")))
This fails because all values are read as strings by configparser and now all attributes are strings. parser.items("Section") looks like this:
[('path', '"D:\\"'), ('number', '10.0'), ('boolean', 'False')]
Now I could go and specify the floats, integers, and booleans by their keys and use the corresponding methods parser.getfloat, getint, and getboolean to get the right python types out. However, that means making an extra list of keys and a loop to get them for each data type, which i don't want. Furthermore, even the path is now double quoted and i need to start removing quotes.
This behavior makes ConfigParser almost completely worthless to me and I am doubting if I am using it correctly an if ConfigParser is the best option for my goal, which is simply to write object attributes to a file and at a later time read the file and add the parameters to a new object as attributes. Can I use ConfigParser for this effectively? Or should I start looking for a different method?
INI is not JSON. There are no data types. There are sections and key/value pairs. Stuff before the = is the key, stuff after it is the value. Everything is text.
There are no "strings", which means there is no need to double quote anything. The same goes for "escaped" backslashes. The concept of escaping does not exist in the INI file format.
So, first off, your file should be looking like this:
[Section]
path = D:\
number = 10.0
boolean = False
Next, I consider this a dangerous operation
parser.read('file.ini')
self.__dict__.update(dict(parser.items("Section")))
because it potentially trashes your class instance with arbitrary values from a text file that might contain garbage, but when you can swear that the file will always be fine, well, do it if you must.
I would write a more explicit way of reading and validating config data. I sense your reason not to do that is laziness or a false sense of simplicity; both of these reasons are not very good.
If you want a semi-automated way of type conversion, tag the keys with a data type.
[Section]
s_path = D:\
f_number = 10.0
b_boolean = False
and write a function that knows how to handle them and throws when something is not right.
def type_convert(items):
result = []
for (key, value) in items:
type_tag = key[:2]
if type_tag == "s_":
result.append((key[2:], value))
elif type_tag == "f_":
result.append((key[2:], float(value)))
elif type_tag == "b_":
result.append((key[2:], bool(value)))
else:
raise ValueError('Invalid type tag "%s" found in ini file.' % type_tag)
# alternatively: "everything else defaults to string"
return result
which you can use to make the operation somewhat more convenient:
self.__dict__.update(dict(type_convert(parser.items("Section"))))
Of course you still run the risk of trashing your class instance by overriding keys that should not be overridden.
I'm a beginner of python. My question is while compiling a project using python, how to make a user-input variable an attribute.
For example:
class supermarket:
num=int(input('enter a no.'))
def __init__(self,num):
self.ini=''
def odd_even(self,num):
if num%2==0:
self.ini='even'
else:
self.ini='odd'
#calling
pallavi=supermarket()
pallavi.(num)
Here, it's showing the error that there is no attribute called num.
What should I do?
This is just a summary and leaves a lot out, but basically, your num should go inside the __init__() call as self.num. So:
class supermarket:
def __init__(self):
self.ini = ''
self.num = int(input('enter a no.'))
# etc.
Then to access the attribute:
pallavi = supermarket()
pallavi.num # No parentheses needed
There's lots more to classes in Python that I don't have time to go into right now, but I'll touch on one thing: until you know what you're doing, all assignments in a class should go inside a function, not in the class definition itself. If you have a statement with a = sign in it that's in the class, not in a function (like the num=int(input("enter a no.")) statement in your example), it's going to fail and you won't understand why.
The reason why goes into the difference between "class variables" and "instance variables", but it might be too soon for you to wrestle with that concept. Still, it might be worth taking a look at the Python tutorial's chapter on classes. If you don't understand parts of that tutorial, don't worry about it yet -- just learn a few concepts, keep on writing code, then go back later and read the tutorial again and a few more concepts may become clear to you.
Good luck!
You have numerous problems here:
num = int(input(...)) assigns a class attribute - this code runs when the class is defined, not when an instance is created, and the attribute will be shared by all instances of the class;
Despite defining a second num parameter to __init__, you call pallavi = supermarket() without passing the argument;
Also, why is num a parameter of odd_even - if it's an attribute, access it via self; and
pallavi.(num) is not correct Python syntax - attribute access syntax is object.attr, the parentheses are a SyntaxError.
I think what you want is something like:
class Supermarket(): # note PEP-8 naming
# no class attributes
def __init__(self, num):
self.num = num # assign instance attribute
self.ini = 'odd' if num % 2 else 'even' # don't need separate method
#classmethod # method of the class, rather than of an instance
def from_input(cls):
while True:
try:
num = int(input('Enter a no.: ')) # try to get an integer
except ValueError:
print("Please enter an integer.") # require valid input
else:
return cls(num) # create class from user input
This separates out the request for user input from the actual initialisation of the instance, and would be called like:
>>> pallavi = Supermarket.from_input()
Enter a no.: foo
Please enter an integer.
Enter a no.: 12
>>> pallavi.num
12
>>> pallavi.ini
'even'
As you mention 3.2 and 2.7, note that input should be replaced with raw_input when using 2.x.
The -builtin option of SWIG has the advantage of being faster, and of being exempt of a bug with multiple inheritance.
The setback is I can't set any attribute on the generated classes or any subclass :
-I can extend a python builtin type like list, without hassle, by subclassing it :
class Thing(list):
pass
Thing.myattr = 'anything' # No problem
-However using the same approach on a SWIG builtin type, the following happens :
class Thing(SWIGBuiltinClass):
pass
Thing.myattr = 'anything'
AttributeError: type object 'Thing' has no attribute 'myattr'
How could I work around this problem ?
I found a solution quite by accident. I was experimenting with metaclasses, thinking I could manage to override the setattr and getattr functions of the builtin type in the subclass.
Doing this I discovered the builtins already have a metaclass (SwigPyObjectType), so my metaclass had to inherit it.
And that's it. This alone solved the problem. I would be glad if someone could explain why :
SwigPyObjectType = type(SWIGBuiltinClass)
class Meta(SwigPyObjectType):
pass
class Thing(SWIGBuiltinClass):
__metaclass__ = Meta
Thing.myattr = 'anything' # Works fine this time
The problem comes from how swig implemented the classes in "-builtin" to be just like builtin classes (hence the name).
builtin classes are not extensible - try to add or modify a member of "str" and python won't let you modify the attribute dictionary.
I do have a solution I've been using for several years.
I'm not sure I can recommend it because:
It's arguably evil - the moral equivalent of casting away const-ness in C/C++
It's unsupported and could break in future python releases
I haven't tried it with python3
I would be a bit uncomfortable using "black-magic" like this in production code - it could break and is certainly obscure - but at least one giant corporation IS using this in production code
But.. I love how well it works to solve some obscure features we wanted for debugging.
The original idea is not mine, I got it from:
https://gist.github.com/mahmoudimus/295200 by Mahmoud Abdelkader
The basic idea is to access the const dictionary in the swig-created type object as a non-const dictionary and add/override any desired methods.
FYI, the technique of runtime modification of classes is called monkeypatching, see https://en.wikipedia.org/wiki/Monkey_patch
First - here's "monkeypatch.py":
''' monkeypatch.py:
I got this from https://gist.github.com/mahmoudimus/295200 by Mahmoud Abdelkader,
his comment: "found this from Armin R. on Twitter, what a beautiful gem ;)"
I made a few changes for coding style preferences
- Rudy Albachten April 30 2015
'''
import ctypes
from types import DictProxyType, MethodType
# figure out the size of _Py_ssize_t
_Py_ssize_t = ctypes.c_int64 if hasattr(ctypes.pythonapi, 'Py_InitModule4_64') else ctypes.c_int
# python without tracing
class _PyObject(ctypes.Structure):
pass
_PyObject._fields_ = [
('ob_refcnt', _Py_ssize_t),
('ob_type', ctypes.POINTER(_PyObject))
]
# fixup for python with tracing
if object.__basicsize__ != ctypes.sizeof(_PyObject):
class _PyObject(ctypes.Structure):
pass
_PyObject._fields_ = [
('_ob_next', ctypes.POINTER(_PyObject)),
('_ob_prev', ctypes.POINTER(_PyObject)),
('ob_refcnt', _Py_ssize_t),
('ob_type', ctypes.POINTER(_PyObject))
]
class _DictProxy(_PyObject):
_fields_ = [('dict', ctypes.POINTER(_PyObject))]
def reveal_dict(proxy):
if not isinstance(proxy, DictProxyType):
raise TypeError('dictproxy expected')
dp = _DictProxy.from_address(id(proxy))
ns = {}
ctypes.pythonapi.PyDict_SetItem(ctypes.py_object(ns), ctypes.py_object(None), dp.dict)
return ns[None]
def get_class_dict(cls):
d = getattr(cls, '__dict__', None)
if d is None:
raise TypeError('given class does not have a dictionary')
if isinstance(d, DictProxyType):
return reveal_dict(d)
return d
def test():
import random
d = get_class_dict(str)
d['foo'] = lambda x: ''.join(random.choice((c.upper, c.lower))() for c in x)
print "and this is monkey patching str".foo()
if __name__ == '__main__':
test()
Here's a contrived example using monkeypatch:
I have a class "myclass" in module "mystuff" wrapped with swig -python -builtin
I want to add an extra runtime method "namelen" that returns the length of the name returned by myclass.getName()
import mystuff
import monkeypatch
# add a "namelen" method to all "myclass" objects
def namelen(self):
return len(self.getName())
d = monkeypatch.get_class_dict(mystuff.myclass)
d['namelen'] = namelen
x = mystuff.myclass("xxxxxxxx")
print "namelen:", x.namelen()
Note that this can also be used to extend or override methods on builtin python classes, as is demonstrated in the test in monkeypatch.py: it adds a method "foo" to the builtin str class that returns a copy of the original string with random upper/lower case letters
I would probably replace:
# add a "namelen" method to all "myclass" objects
def namelen(self):
return len(self.getName())
d = monkeypatch.get_class_dict(mystuff.myclass)
d['namelen'] = namelen
with
# add a "namelen" method to all "myclass" objects
monkeypatch.get_class_dict(mystuff.myclass)['namelen'] = lambda self: return len(self.getName())
to avoid extra global variables