Checking variable type in Ruby - python

I have an issue checking variable types in ruby. Here is a sample code of python that I would like to replicate in ruby. I would like to check the input type: whether string, int, or list, and proceed to a specific printing action.
def printing (input):
if type(input) == type(""):
pass
elif type(input) == type(1):
pass
elif type(input) == type([]):
pass
elif type(input) == type({}):
pass
elif type(input) == type(()):
pass
I cannot find a method that will do this in ruby. The code below is what I want it to look like. I am assuming that I have to check the type at the case stage.
def printing (element)
case element
when element.type("")
puts element
when element.type(2)
puts element
when element.type({})
element.each_pair { |name, val| print "#{name} : #{value}"}
when element.type([])
element.each {|x| print x}
end
end

I think you are looking for Object#class. Here:
element = {}
element.class
# => Hash
a = []
a.class
# => Array
This will make your switch case as follows:
case element
when String
# do something
when Fixnum
# do something
when Hash
# do something
when Array
# do something
end
Note:
As mentioned by #ndn in comments below, case statement should not have .class in it (which I had initially in my answer). You can find the explanation here.

This is not the "correct answer", I would simply like to point out that you should not use type in python you should use isinstance instead
isinstance(input, list) # test for list
isinstance(inpit, [float, int]) # test for number
if you are using python 3 you can check for abstract base classes
import collections
isinstance(input, collections.abs.Sequence) # sequence = tuple, list and a lot of other stuff that behaves that way

Related

Python: Split String and convert to other type

I have a function which could get a String formatted like this:
"true"^^<http://www.w3.org/2001/XMLSchema#boolean>
"100"^^<http://www.w3.org/2001/XMLSchema#int>
Now i want to split the String on the ^^ Characters and convert the first part of the string based on the second part. I also want to remove the " first before converting.
This is my code which i use for this:
def getValue(tObject):
toReturn = tObject.split("^^")
if len(toReturn) == 2:
if toReturn[1] == "<http://www.w3.org/2001/XMLSchema#boolean>":
return bool(toReturn[0].replace('"', ""))
elif toReturn[1] == "<http://www.w3.org/2001/XMLSchema#int>":
return int(toReturn[0].replace('"', ""))
return None
But i'm not so happy with it. Is there maybe a more elegant (pythonic) way to archive this?
You can use a regex, to
check if the given value is valid
retrieve the value to cast, and the way to cast
PATTERN = re.compile(r'"(.*)"\^\^<http:.*#(\w+)>')
types = {"boolean": bool, "int": int}
def getValue(value):
m = PATTERN.fullmatch(value)
return types[m.group(2)](m.group(1)) if m else None
Instead of if len(...) you could just try to unpack the result and except a ValueError. Then you can use a dict for the types and str.strip instead of str.replace:
types = {'boolean': bool, 'int': int}
try:
value, type_hint = tObject.split('^^')
except ValueError:
return None
else:
return types[type_hint.rstrip('>').rsplit('#', 1)[1]](value.strip('"'))
Firstly, you could remove return None, since the function returns None by default.
Secondly, you could use toReturn[1].endswith("boolean>") to match the end of the string, instead of matching the whole string with toReturn[1] == "<http://www.w3.org/2001/XMLSchema#boolean>". Same with the int string as well.
Thirdly, you could store the return value in one variable before the if..elif, then you don't have to calculate it twice for each condition.
Code:
def getValue(tObject):
toReturn = tObject.split("^^")
if len(toReturn) == 2:
return_value = toReturn[0].replace('"', "")
if toReturn[1].endswith("boolean>"):
return bool(return_value)
elif toReturn[1].endswith("int>"):
return int(return_value)
This might not be much of a logic improvement, but the code does look less cluttered now. If you wan't more terse, "pythonic" ways of doing this problem, the other answers might be more suitable.

Looping through list of functions in a function in Python dynamically

I'd like to see if it's possible to run through a list of functions in a function. The closest thing I could find is looping through an entire module. I only want to use a pre-selected list of functions.
Here's my original problem:
Given a string, check each letter to see if any of the 5 tests fulfill.
If a minimum of 1 letter passes a check, return True.
If all letters in the string fails the check, return False.
For each letter in the string, we will check these functions: isalnum(), isalpha(), isdigit(), islower(), isupper()
The result of each test should print to different lines.
Sample Input
qA2
Sample Output (must print to separate lines, True if at least one letter passes, or false is all letters fail each test):
True
True
True
True
True
I wrote this for one test. Of course I could just write 5 different sets of code but that seems ugly. Then I started wondering if I could just loop through all the tests they're asking for.
Code for just one test:
raw = 'asdfaa3fa'
counter = 0
for i in xrange(len(raw)):
if raw[i].isdigit() == True: ## This line is where I'd loop in diff func's
counter = 1
print True
break
if counter == 0:
print False
My fail attempt to run a loop with all the tests:
raw = 'asdfaa3fa'
lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]
counter = 0
for f in range(0,5):
for i in xrange(len(raw)):
if lst[f] == True: ## loop through f, which then loops through i
print lst[f]
counter = 1
print True
break
if counter == 0:
print False
So how do I fix this code to fulfill all the rules up there?
Using info from all the comments - this code fulfills the rules stated above, looping through each method dynamically as well.
raw = 'ABC'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
for func in functions:
print any(func(letter) for letter in raw)
getattr approach (I think this is called introspection method?)
raw = 'ABC'
meths = ['isalnum', 'isalpha', 'isdigit', 'islower', 'isupper']
for m in meths:
print any(getattr(c,m)() for c in raw)
List comprehension approach:
from __future__ import print_function ## Changing to Python 3 to use print in list comp
raw = 'ABC'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
solution = [print(func(raw)) for func in functions]
The way you are looping through a list of functions is slightly off. This would be a valid way to do it. The functions you need to store in the list are the generic string functions given by str.funcname. Once you have those list of functions, you can loop through them using a for loop, and just treat it like a normal function!
raw = 'asdfaa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper] # list of functions
for fn in functions: # iterate over list of functions, where the current function in the list is referred to as fn
for ch in raw: # for each character in the string raw
if fn(ch):
print(True)
break
Sample outputs:
Input Output
===================================
"qA2" -----> True True True True True
"asdfaa3fa" -----> True True True True
Also I notice you seem to use indexing for iteration which makes me feel like you might be coming from a language like C/C++. The for in loop construct is really powerful in python so I would read up on it (y).
Above is a more pythonic way to do this but just as a learning tool, I wrote a working version that matches how you tried to do it as much as possible to show you where you went wrong specifically. Here it is with comments:
raw = 'asdfaa3fa'
lst = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper] # notice youre treating the functions just like variables and aren't actually calling them. That is, you're writing str.isalpha instead of str.isalpha()
for f in range(0,5):
counter = 0
for i in xrange(len(raw)):
if lst[f](raw[i]) == True: # In your attempt, you were checking if lst[f]==True; lst[f] is a function so you are checking if a function == True. Instead, you need to pass an argument to lst[f](), in this case the ith character of raw, and check whether what that function evaluates to is true
print lst[f]
counter = 1
print True
break
if counter == 0:
print False
Okay, so the first question is easy enough. The simple way to do it is just do
def foo(raw):
for c in raw:
if c.isalpha(): return True
if c.isdigit(): return True
# the other cases
return False
Never neglect the simplest thing that could work.
Now, if you want to do it dynamically -- which is the magic keyword you probably needed, you want to apply something like this (cribbed from another question):
meths = [isalnum, isalpha, isdigit, islower, isupper]
for c in raw:
for m in meths:
getattr(c, m)()
Warning, this is untested code meant to give you the idea. The key notion here is that the methods of an object are attributes just like anything else, so, for example getattr("a", "isalpha")() does the following:
Uses getattr to search the attributes dictionary of "a" for a method named isalpha
Returns that method itself -- <function isalpha>
then invokes that method using the () which is the function application operator in Python.
See this example:
In [11]: getattr('a', 'isalpha')()
Out[11]: True
All the other answers are correct, but since you're a beginner, I want to point out the problem in your code:
lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]
First: Not sure which value i currently has in your code snipped, but it seems to point somewhere in the string - which results in single characters being evaluated, not the whole string raw.
Second: When you build your list, you are already calling the methods you want to insert, which has the effect that not the functions themself get inserted, but their return values (that's why you're seeing all those True values in your print statement).
Try changing your code as follows:
lst = [raw.isalnum, raw.isalpha, raw.isdigit, raw.islower, raw.isupper]
I'm going to guess that you're validating password complexity, and I'm also going to say that software which takes an input and says "False" and there's no indication why is user-hostile, so the most important thing is not "how to loop over nested char function code wizardry (*)" but "give good feedback", and suggest something more like:
raw = 'asdfaa3fa'
import re
def validate_password(password):
""" This function takes a password string, and validates it
against the complexity requirements from {wherever}
and returns True if it's complex enough, otherwise False """
if not re.search('\d', password):
print("Error: password needs to include at least one number")
return False
elif not re.search('[a-z]', password):
print("Error: password must include at least one lowercase letter")
return False
elif not re.search('[A-Z]', password):
print("Error: password must include at least one uppercase letter")
return False
print("Password is OK")
return True
validate_password(raw)
Try online at repl.it
And the regex searching checks ranges of characters and digits in one call, which is neater than a loop over characters.
(PS. your functions overlap; a string which has characters matching 'isupper', 'islower' and 'isnumeric' already has 'isadigit' and 'isalnum' covered. More interesting would be to handle characters like ! which are not upper, lower, digits or alnum).
(*) function wizardry like the other answers is normally exactly what I would answer, but there's so much of that already answered that I may as well answer the other way instead :P
To answer the original question:
raw = 'asdfa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
isanything = [func(raw) for func in functions]
print repr(isanything)
Since you are looping through a list of simple items and trying to find if all of the functions has any valid results, you can simply define the list of functions you want to call on the input and return that. Here is a rather pythonic example of what you are trying to achieve:
def checker(checks, value):
return all(any(check(r) for r in value) for check in checks)
Test it out:
>>> def checker(checks, value):
... return all(any(check(r) for r in value) for check in checks)
...
>>> checks = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
>>> checker(checks, 'abcdef123ABC')
True
>>> checker(checks, 'abcdef123')
False
>>>
You can use introspection to loop through all of an object's attributes, whether they be functions or some other type.
However you probably don't want to do that here, because str has lots of function attributes, and you're only interested in five of them. It's probably better to do as you did and just make a list of the five you want.
Also, you don't need to loop over each character of the string if you don't want to; those functions already look at the whole string.
Check out this one-line solution for your problem. That problem is from HackerRank. I loop through a list of functions using the built-in getattr function.
s='qA2'
[print(bool(list(filter(lambda x : getattr(x, func)(),s)))) for func in ['isalnum','isalpha','isdigit','islower','isupper']]

Python "if" statement - if xpath is true

im trying to code in python (very new to it) and need to check if an xpath is there then variable = the xpath but if not variable = string.
An example is below
if tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()') = true
$value = tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()')
else
$value = ''
You should really start by doing the whole official tutorial before anything else, as it will anwser your question.
First point : Python objects all have a 'truth' value in a boolean context, which is defined by the object's type and actual value. For builtin types, all empty containers (lists, dicts, sets etc), the empty string, all numerical zeros and the None object are false, everything else is true. For non builtin types you'll have to check the package's documentation.
The builtin type bool will also tell you the boolean value of a given object, so all of the below tests are equivalent:
if myobj:
xxx
if bool(myobj):
xxx
if bool(myobj) == True:
xxx
BUT keep in mind that it doesn't imply that bool(myobj) is the same as myobj - the first one is the boolean value of your object, so the following is NOT equivalent (unless myobj is one of True, 1 or 1.0):
if myobj == True:
xxx
Now wrt/ your actual code snippet: it's not valid Python (bad indentation, invalid identifier $value, invalid use of the assignment operator =, missing : after the if and else statements, wrong capitalization for True...)
Assuming you meant:
# let's make this at least readable:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
if tree.xpath(path) == True:
value = tree.xpath(path)
else:
value = ''
The obvious error is the explicit test against True (tree.xpath() doesn't return a boolean). You either have to explicitely cast the return of tree.xpath() to a boolean (which is quite verbose, totally useless and definitly unpythonic) or just let Python do the right thing by removing the == True part of your test.
As a side note: calling tree.xpath twice in a row with the same argument is a waste of processor cycle (both calls will return the same value), so use a variable instead - it will also make your code much more readable and maintainable. The Pythonic version of your code would look something like:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
found = tree.xpath(path)
value = found if found else ''
or even more simply:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
value = tree.xpath(path) or ''
since the or operator will not yield a boolean value but either the first of it's operand that has a true value or the last operand if none has a true value.
#No need to test == if value is bool. and you not check, you assign value with one =
if anything:
#Then do this
else:
#Do this

Define datatype in Python

I have some inkling of how this might work, but I do not know the exact syntax of how to do it.
An example:
def function(string):
string = string + "A"
How will the function know that what I am inputting is a string?
Is it something along the lines of...
string = type.str
There are some ways to check the type of a variable. First, you could check if the parameter is an instance of str:
def isstring(parameter):
return isinstance(parameter, str)
Another way could be to try to concatenate a string (in this case "") with the parameter and catch eventually exceptions (TypeError exception):
def isstring(parameter):
try:
parameter += ""
return True
except TypeError:
return False
Another way could be to use type (similar to isinstance, but difference mostly when polymorphism is involved):
def isstr(parameter):
return type(parameter) == str
You could also use assert, but if you want just to check if a parameter is of a certain type, I would adopt the first case.
No, you could NOT, python is dynamic but not static, so it could not know the argument type at "compile time", instead, you could check the input type by assert.
def fun(string):
assert isinstance(string, basestring) # we usually check if it type is basestring as this works fine for both ASCII string and Unicode.
string = string + "A"
return string
if __name__ == '__main__':
fun(2)

Mixing ints and function pointers in python dict values

I'm making a finite state machine to iterate over some text for speaker, verb, and quote identification. Everything is going fine, but I'm frustrated I cannot get my dictionary to work just the way I want it to. I want to use a dictionary like this, that has both function pointers and ints as values:
chars = ['a','b','c']
whatever = ['cheese']
state = 0
def function():
# don't know what's going on, ask user to check
transitions = {
0: {chars: 1, whatever: 2, '“': 4},
1: {chars: 3, '“': function},
etc.
}
for item in data:
for transition in transitions[state]:
if item in transition or transition in item:
state = transitions[state][item]
However, this code doesn't call the function if it finds it, or if I have it call the function, it errors on calling an int.
PS I'm not looking to use a library, etc.
You can use the object type to decide what to do with it. I don't want to get into other issues with the code, but for the basic idea, here's a function that returns an int or calls a function depending on the value type.
def action(value):
if isinstance(value, int):
return value
elif callable(value):
return value()
else:
raise ValueError("action does not work with %s objects" % type(value))

Categories

Resources